compute_it/
lib.rs

1#![doc = include_str!("../README.MD")]
2#![warn(missing_docs)]
3#![deny(warnings)]
4#![allow(private_bounds)]
5
6use std::{
7    collections::HashMap,
8    fmt::{Debug, Formatter},
9    marker::PhantomData,
10    ops::Deref,
11    sync::{atomic::AtomicBool, Arc, RwLock, RwLockReadGuard},
12};
13
14use ccutils::{
15    key::Key,
16    sync::{arc_mutex_new, arc_rw_lock_new, ArcMutex, ArcRwLock},
17};
18use linked_hash_map::LinkedHashMap;
19
20//   ____                            _        _   _             ___                   _   ___       _             __
21//  / ___|___  _ __ ___  _ __  _   _| |_ __ _| |_(_) ___  _ __ |_ _|_ __  _ __  _   _| |_|_ _|_ __ | |_ ___ _ __ / _| __ _  ___ ___
22// | |   / _ \| '_ ` _ \| '_ \| | | | __/ _` | __| |/ _ \| '_ \ | || '_ \| '_ \| | | | __|| || '_ \| __/ _ \ '__| |_ / _` |/ __/ _ \
23// | |__| (_) | | | | | | |_) | |_| | || (_| | |_| | (_) | | | || || | | | |_) | |_| | |_ | || | | | ||  __/ |  |  _| (_| | (_|  __/
24//  \____\___/|_| |_| |_| .__/ \__,_|\__\__,_|\__|_|\___/|_| |_|___|_| |_| .__/ \__,_|\__|___|_| |_|\__\___|_|  |_|  \__,_|\___\___|
25//                      |_|                                              |_|
26
27/// Trait for building value in the computation graph
28trait ComputationValueType {
29    /// Type of the value
30    type Type: 'static + Send + Sync;
31}
32
33/// Trait for building value in the computation graph
34trait ComputationInputInterface: ComputationValueType {
35    type InputReaderType: InputReader<Self::Type>;
36    fn id(&self) -> ccutils::key::Key;
37    /// Prepare the value
38    fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>);
39}
40
41//  ___                   _   ____                _
42// |_ _|_ __  _ __  _   _| |_|  _ \ ___  __ _  __| | ___ _ __
43//  | || '_ \| '_ \| | | | __| |_) / _ \/ _` |/ _` |/ _ \ '__|
44//  | || | | | |_) | |_| | |_|  _ <  __/ (_| | (_| |  __/ |
45// |___|_| |_| .__/ \__,_|\__|_| \_\___|\__,_|\__,_|\___|_|
46//           |_|
47
48/// This trait is used to access the result of a computation, or the content of a variable.
49/// Generally as stored in
50trait InputReader<T>: Sync + Send + 'static {
51    type InputGuard<'a>; //: Deref<Target = T>;
52    fn read_input<'a>(&'a self) -> Self::InputGuard<'a>;
53}
54
55impl<T> InputReader<T> for RwLock<T>
56where
57    T: Sync + Send + 'static,
58{
59    type InputGuard<'a> = RwLockReadGuard<'a, T>;
60    fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
61        self.read().unwrap()
62    }
63}
64
65impl<C, T> InputReader<T> for Arc<C>
66where
67    C: InputReader<T>,
68{
69    type InputGuard<'a> = C::InputGuard<'a>;
70    fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
71        self.deref().read_input()
72    }
73}
74
75// __     __        ___                   _   ____                _
76// \ \   / /__  ___|_ _|_ __  _ __  _   _| |_|  _ \ ___  __ _  __| | ___ _ __
77//  \ \ / / _ \/ __|| || '_ \| '_ \| | | | __| |_) / _ \/ _` |/ _` |/ _ \ '__|
78//   \ V /  __/ (__ | || | | | |_) | |_| | |_|  _ <  __/ (_| | (_| |  __/ |
79//    \_/ \___|\___|___|_| |_| .__/ \__,_|\__|_| \_\___|\__,_|\__,_|\___|_|
80//                           |_|
81
82trait VecInputGuard<C, Marker>
83where
84    VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
85{
86    fn as_input_value<'a>(&'a self) -> VecFnArg<'a, C, Marker>;
87}
88
89trait VecInputReader<C, Marker>: Send + Sync + 'static
90where
91    C: Send + Sync + 'static,
92    VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
93{
94    fn read_vec_input(&self) -> Box<dyn VecInputGuard<C, Marker> + '_>;
95}
96
97struct VecComputationFArgsSelectorTraitBridge<'b, C> {
98    bridge: Box<dyn Deref<Target = C> + 'b>,
99}
100
101impl<'b, C> VecInputGuard<C, DefaultVariableMarker>
102    for VecComputationFArgsSelectorTraitBridge<'b, C>
103where
104    for<'c> VecComputationFArgsSelector<C, DefaultVariableMarker>:
105        VecComputationFArgsSelectorTrait<FArgs<'c> = &'c C>,
106{
107    fn as_input_value<'a>(&'a self) -> VecFnArg<'a, C, DefaultVariableMarker> {
108        let r: &C = self.bridge.deref();
109        r
110    }
111}
112
113impl<C, T> VecInputReader<C, DefaultVariableMarker> for T
114where
115    T: InputReader<C>,
116    C: Send + Sync + 'static,
117    for<'a> VecComputationFArgsSelector<C, DefaultVariableMarker>:
118        VecComputationFArgsSelectorTrait<FArgs<'a> = &'a C>,
119    for<'a> <T as InputReader<C>>::InputGuard<'a>: Deref<Target = C>,
120{
121    fn read_vec_input(&self) -> Box<dyn VecInputGuard<C, DefaultVariableMarker> + '_> {
122        Box::new(VecComputationFArgsSelectorTraitBridge::<C> {
123            bridge: Box::new(self.read_input()),
124        })
125    }
126}
127
128//  ____                            _
129// |  _ \  ___ _ __   ___ _ __   __| | ___ _ __   ___ _   _
130// | | | |/ _ \ '_ \ / _ \ '_ \ / _` |/ _ \ '_ \ / __| | | |
131// | |_| |  __/ |_) |  __/ | | | (_| |  __/ | | | (__| |_| |
132// |____/ \___| .__/ \___|_| |_|\__,_|\___|_| |_|\___|\__, |
133//            |_|                                     |___/
134
135struct Dependency {
136    key: Key,
137    dependencies: RwLock<HashMap<Key, Arc<Dependency>>>,
138    dependents: RwLock<HashMap<Key, Arc<Dependency>>>,
139    outdated: AtomicBool,
140}
141
142impl Debug for Dependency {
143    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
144        f.debug_struct("")
145            .field("key", &self.key)
146            .field("dependencies", &self.dependencies)
147            .field("dependends count", &self.dependents.read().unwrap().len())
148            .finish()
149    }
150}
151
152impl Dependency {
153    fn new() -> Arc<Self> {
154        Arc::new(Self {
155            key: Key::new(),
156            dependencies: Default::default(),
157            dependents: Default::default(),
158            outdated: AtomicBool::new(false),
159        })
160    }
161    fn from_key(key: Key) -> Arc<Self> {
162        Arc::new(Self {
163            key,
164            dependencies: Default::default(),
165            dependents: Default::default(),
166            outdated: AtomicBool::new(false),
167        })
168    }
169    fn notify_all(&self) {
170        self.outdated
171            .store(true, std::sync::atomic::Ordering::Relaxed);
172        for (_, dep) in self.dependencies.read().unwrap().iter() {
173            dep.notify_all();
174        }
175    }
176    fn insert_dependency(&self, d: Arc<Dependency>) {
177        self.dependencies.write().unwrap().insert(d.key.clone(), d);
178    }
179    fn insert_dependent(&self, d: Arc<Dependency>) {
180        self.dependents.write().unwrap().insert(d.key.clone(), d);
181    }
182    fn remove_dependency(&self, key: &Key) {
183        if let Some(dep) = self.dependencies.write().unwrap().remove(key) {
184            dep.dependents.write().unwrap().remove(&self.key);
185        }
186    }
187    fn link(dependency: &Arc<Dependency>, dependent: Arc<Dependency>) {
188        dependent.insert_dependency(dependency.clone());
189        dependency.insert_dependent(dependent);
190    }
191}
192
193//   ____                            _        _   _             ____        _ _     _
194//  / ___|___  _ __ ___  _ __  _   _| |_ __ _| |_(_) ___  _ __ | __ ) _   _(_) | __| | ___ _ __
195// | |   / _ \| '_ ` _ \| '_ \| | | | __/ _` | __| |/ _ \| '_ \|  _ \| | | | | |/ _` |/ _ \ '__|
196// | |__| (_) | | | | | | |_) | |_| | || (_| | |_| | (_) | | | | |_) | |_| | | | (_| |  __/ |
197//  \____\___/|_| |_| |_| .__/ \__,_|\__\__,_|\__|_|\___/|_| |_|____/ \__,_|_|_|\__,_|\___|_|
198//                      |_|
199
200/// Used to build computation.
201trait ComputationBuilder<T> {
202    /// Argument for the computation functor
203    type FunctorArgument<'a>;
204    /// Prepare the computation
205    fn prepare<'b>(
206        &self,
207        dependency: &Arc<Dependency>,
208        formula: impl for<'a> Fn(Self::FunctorArgument<'a>) -> T + 'b + Send + Sync,
209    ) -> impl Fn() -> T + 'b + Send + Sync;
210}
211
212trait ComputationVecBuilder<T, Marker> {
213    fn prepare(
214        &self,
215        dependency: &Arc<Dependency>,
216    ) -> LinkedHashMap<Key, Box<dyn VecInputReader<T, Marker>>>;
217}
218
219macro_rules! computation_builder {
220    ($($type_idx: tt),*) => {
221        paste::paste!{
222            impl<'b, T, $( [<VT $type_idx>], )*> ComputationBuilder<T>
223                for ($(&'b [<VT $type_idx>], )*)
224            where
225                $(
226                    [<VT $type_idx>]: ComputationInputInterface,
227                    for<'a> <<[<VT $type_idx>] as ComputationInputInterface>::InputReaderType as InputReader
228                    <<[<VT $type_idx>] as ComputationValueType>::Type>>::InputGuard<'a>: Deref<Target = <[<VT $type_idx>] as ComputationValueType>::Type>,
229                )*
230            {
231                type FunctorArgument<'a> = ( $(&'a [<VT $type_idx>]::Type, )*);
232                fn prepare<'c>(
233                    &self,
234                    dependency: &Arc<Dependency>,
235                    formula: impl for<'a> Fn(Self::FunctorArgument<'a>) -> T + 'c + Send + Sync,
236                ) -> impl Fn() -> T + 'c + Send + Sync {
237                    $(
238                        let ([<v $type_idx>], [<dep $type_idx>]) = self.$type_idx.prepare_value();
239                        Dependency::link(&dependency, [<dep $type_idx>]);
240                    )*
241
242                    move || {
243                        $(
244                            let [<v $type_idx>] = [<v $type_idx>].read_input();
245                        )*
246                        formula(($( [<v $type_idx>].deref(), )*))
247                    }
248                }
249            }
250            impl<'b, T, Marker, $( [<VT $type_idx>], )*> ComputationVecBuilder<T, Marker>
251                for ($(&'b [<VT $type_idx>], )*)
252            where
253                $(
254                    [<VT $type_idx>]: ComputationInputInterface<Type = T>,
255                    <[<VT $type_idx>] as ComputationInputInterface>::InputReaderType: VecInputReader<T, Marker>,
256                )*
257                T: Sync + Send + 'static,
258                VecComputationFArgsSelector<T, Marker>: VecComputationFArgsSelectorTrait,
259            {
260
261                fn prepare(&self,
262                    dependency: &Arc<Dependency>) -> LinkedHashMap<Key, Box<dyn VecInputReader<T, Marker>>>
263
264                {
265                    let mut variables: LinkedHashMap<Key, Box<dyn VecInputReader<T, Marker>>> = Default::default();
266
267                    $(
268                        let ([<v $type_idx>],  [<dep $type_idx>]) = self.$type_idx.prepare_value();
269                        let id = [<dep $type_idx>].key.clone();
270                        Dependency::link(&dependency, [<dep $type_idx>]);
271                        let [<v $type_idx>]: Box<dyn VecInputReader<T, Marker>> = Box::new([<v $type_idx>]);
272                        variables.insert(id, [<v $type_idx>]);
273                    )*
274                    variables
275                }
276            }
277
278            ////////// Support for tuple of inputs
279
280            impl<$( [<VT $type_idx>], )*> ComputationValueType for ($( &[<VT $type_idx>], )*)
281            where
282            $(
283                [<VT $type_idx>]: ComputationInputInterface,
284            )*
285            {
286                type Type = ($([<VT $type_idx>]::Type,)*);
287            }
288            impl<$( [<T $type_idx>], )* $([<IRT $type_idx>], )*> InputReader<($([<T $type_idx>], )*)> for ($([<IRT $type_idx>], )*)
289            where
290            $(
291                [<IRT $type_idx>]: InputReader<[<T $type_idx>]>,
292            )*
293            {
294                type InputGuard<'a> = ($([<IRT $type_idx>]::InputGuard<'a>,)*);
295                fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
296                    (
297                        $(
298                            self.$type_idx.read_input(),
299                        )*
300                    )
301                }
302            }
303
304            impl<$( [<T $type_idx>], )* $( [<VT $type_idx>], )*> ComputationInputInterface for ($( &[<VT $type_idx>], )*)
305            where
306                $(
307                    [<VT $type_idx>]: ComputationInputInterface<Type = [<T $type_idx>]>,
308                    [<T $type_idx>]: Send + Sync + 'static,
309                )*
310            {
311                type InputReaderType = ($([<VT $type_idx>]::InputReaderType,)*);
312                fn id(&self) -> Key {
313                    let mut v = Vec::<Key>::new();
314                    $(
315                        v.push(self.$type_idx.id());
316                    )*
317                    Key::combination(v)
318                }
319                fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>) {
320                    let dependency = Dependency::from_key(self.id());
321                    $(
322                        let ([<input_reader $type_idx>], [<dep $type_idx>]) = self.$type_idx.prepare_value();
323                        Dependency::link(&dependency, [<dep $type_idx>]);
324                    )*
325                    (($([<input_reader $type_idx>], )*), dependency)
326                }
327            }
328
329            impl<$( [<T $type_idx>], )*> VecComputationFArgsSelectorTrait
330                for VecComputationFArgsSelector<($( [<T $type_idx>], )*), markers::GroupedVariables>
331            where
332            $(
333                [<T $type_idx>]: 'static,
334            )*
335            {
336                type FArgs<'a> = ($(&'a [<T $type_idx>],)*);
337            }
338
339            impl<'b, $( [<T $type_idx>], )* $( [<IG $type_idx>], )*> VecInputGuard<($( [<T $type_idx>], )*), markers::GroupedVariables>
340                for ($( [<IG $type_idx>], )*)
341            where
342            $(
343                [<T $type_idx>]: 'static,
344                [<IG $type_idx>]: Deref<Target = [<T $type_idx>]>,
345            )*
346            {
347                fn as_input_value<'a>(&'a self) -> VecFnArg<'a, ($( [<T $type_idx>], )*), markers::GroupedVariables> {
348                    ($(self.$type_idx.deref(), )*)
349                }
350            }
351
352
353            impl<$( [<T $type_idx>], )* $([<IRT $type_idx>], )*> VecInputReader<($( [<T $type_idx>], )*), markers::GroupedVariables> for ($([<IRT $type_idx>], )*)
354            where
355            $(
356                [<T $type_idx>]: Send + Sync + 'static,
357                [<IRT $type_idx>]: InputReader<[<T $type_idx>]>,
358                for<'a> <[<IRT $type_idx>] as InputReader<[<T $type_idx>]>>::InputGuard<'a>: Deref<Target = [<T $type_idx>]>,
359            )*
360            {
361                fn read_vec_input(&self) -> Box<dyn VecInputGuard<($( [<T $type_idx>], )*), markers::GroupedVariables> + '_> {
362                    Box::new(
363                        ($(
364                            self.$type_idx.read_input(),
365                        )*)
366                    )
367                }
368            }
369        }
370    };
371}
372
373macro_rules! computation_builder_reversed {
374    ({} {$($reversed:tt),*}) => {
375        computation_builder!($($reversed),*);
376    };
377    ({$first:tt $(, $rest:tt)*} {$($reversed:tt),*}) => {
378        computation_builder_reversed!({$($rest),*} {$first $(, $reversed)*});  // recursion
379    };
380}
381
382macro_rules! computation_builders {
383    ($first_type_idx: tt) => {
384        computation_builder!($first_type_idx);
385    };
386    ($first_type_idx: tt, $($type_idx: tt),*) => {
387        computation_builder_reversed!({$($type_idx),*} {$first_type_idx});
388        computation_builders!($($type_idx),*);
389    }
390}
391computation_builders!(20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
392
393impl<'b, T, Marker> ComputationVecBuilder<T, Marker> for ()
394where
395    T: Sync + Send + 'static,
396{
397    fn prepare(
398        &self,
399        _: &Arc<Dependency>,
400    ) -> LinkedHashMap<Key, Box<dyn VecInputReader<T, Marker>>> {
401        Default::default()
402    }
403}
404
405impl<T, VT> ComputationBuilder<T> for Vec<&VT>
406where
407    VT: ComputationInputInterface<Type = T>,
408    T: Sync + Send + 'static,
409    for<'a> <<VT as ComputationInputInterface>::InputReaderType as InputReader<T>>::InputGuard<'a>:
410        Deref<Target = T>,
411{
412    type FunctorArgument<'a> = Vec<&'a VT::Type>;
413    fn prepare<'b>(
414        &self,
415        dependency: &Arc<Dependency>,
416        formula: impl for<'a> Fn(Self::FunctorArgument<'a>) -> T + 'b + Send + Sync,
417    ) -> impl Fn() -> T + 'b + Send + Sync {
418        let variables = <Vec<&VT> as ComputationVecBuilder<T, DefaultVariableMarker>>::prepare(
419            self, dependency,
420        );
421
422        move || {
423            let unlocked_vars: Vec<_> = variables.iter().map(|(_, v)| v.read_vec_input()).collect();
424            let values: Vec<&T> = unlocked_vars
425                .iter()
426                .map(|uv| -> &T { uv.as_input_value() })
427                .collect();
428            formula(values)
429        }
430    }
431}
432impl<T, VT, Marker> ComputationVecBuilder<T, Marker> for Vec<&VT>
433where
434    VT: ComputationInputInterface<Type = T>,
435    T: Sync + Send + 'static,
436    VecComputationFArgsSelector<T, Marker>: VecComputationFArgsSelectorTrait,
437    <VT as ComputationInputInterface>::InputReaderType: VecInputReader<T, Marker>,
438{
439    fn prepare(
440        &self,
441        dependency: &Arc<Dependency>,
442    ) -> LinkedHashMap<Key, Box<dyn VecInputReader<T, Marker>>> {
443        self.into_iter()
444            .map(|v| {
445                let (getter, v_dependency) = v.prepare_value();
446                let id = v_dependency.key.clone();
447                Dependency::link(&dependency, v_dependency);
448
449                let vm: Box<dyn VecInputReader<T, Marker>> = Box::new(getter);
450                (id, vm)
451            })
452            .collect()
453    }
454}
455
456//   ____                            _        _   _
457//  / ___|___  _ __ ___  _ __  _   _| |_ __ _| |_(_) ___  _ __
458// | |   / _ \| '_ ` _ \| '_ \| | | | __/ _` | __| |/ _ \| '_ \
459// | |__| (_) | | | | | | |_) | |_| | || (_| | |_| | (_) | | | |
460//  \____\___/|_| |_| |_| .__/ \__,_|\__\__,_|\__|_|\___/|_| |_|
461struct ComputationData<T>
462where
463    T: Send + Sync + 'static,
464{
465    result: ArcRwLock<T>,
466    formula: ArcMutex<Box<dyn Fn() -> T + Sync + Send + 'static>>,
467    dependency: Arc<Dependency>,
468}
469
470impl<T> Debug for ComputationData<T>
471where
472    T: Debug + Sync + Send + 'static,
473{
474    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
475        f.debug_struct("").field("result", &self.result).finish()
476    }
477}
478
479impl<T> Clone for ComputationData<T>
480where
481    T: Send + Sync + 'static,
482{
483    fn clone(&self) -> Self {
484        Self {
485            result: self.result.clone(),
486            formula: self.formula.clone(),
487            dependency: self.dependency.clone(),
488        }
489    }
490}
491
492/// `Computation` represent a computation in the graph, with a static structures. Only
493/// the variable values can be changed.
494///
495///
496/// ```rust
497/// # use compute_it::*;
498///
499/// let v1 = Variable::<u32>::new(1);
500/// let v2 = Variable::<u32>::new(2);
501/// let v3 = Variable::<u32>::new(3);
502///
503/// // Create a new computation `c1` with `v1`, `v2` and `v3` as variables.
504/// let c1 = Computation::<u32>::new(|(a, b, c)| a + b + c, (&v1, &v2, &v3));
505/// println!("{} == 6", *c1.read_result());
506///
507/// // Change in `v1` change the result of `c1`.
508/// v1.set(4);
509/// println!("{} == 9", *c1.read_result());
510/// ```
511///
512/// Computation can also be used as input to other computation, and give access to intermediary results:
513///
514/// ```rust
515/// # use compute_it::*;
516///
517/// let v1 = Variable::<u32>::new(1);
518/// let v2 = Variable::<u32>::new(2);
519/// let v3 = Variable::<u32>::new(3);
520///
521/// // Create a new computation `c1` with `v1` and `v2` as variables.
522/// let c1 = Computation::<u32>::new(|(a, b)| a + b, (&v1, &v2));
523/// println!("{} == 3", *c1.read_result());
524///
525/// // Create a new computation `c2` which uses the result of `c1` and the variable `v3`.
526/// let c2 = Computation::<u32>::new(|(a, b)| a + b, (&c1, &v3));
527/// println!("{} == 6", *c1.read_result());
528///
529/// // Change in the value `v1` also changes the result of `c2`.
530/// v1.set(4);
531/// println!("{} == 6", *c1.read_result());
532/// println!("{} == 9", *c2.read_result());
533/// ```
534
535#[derive(Debug)]
536pub struct Computation<T>
537where
538    T: Send + Sync + 'static,
539{
540    data: ComputationData<T>,
541}
542
543impl<T> ComputationValueType for Computation<T>
544where
545    T: Send + Sync + 'static,
546{
547    type Type = T;
548}
549
550impl<T> ComputationInputInterface for Computation<T>
551where
552    T: Send + Sync + 'static,
553{
554    type InputReaderType = ComputationData<T>;
555    fn id(&self) -> Key {
556        self.data.dependency.key.clone()
557    }
558    fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>) {
559        (self.data.clone(), self.data.dependency.clone())
560    }
561}
562
563impl<T> InputReader<T> for ComputationData<T>
564where
565    T: Sync + Send + 'static,
566{
567    type InputGuard<'a> = RwLockReadGuard<'a, T>;
568    fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
569        if self
570            .dependency
571            .outdated
572            .load(std::sync::atomic::Ordering::Relaxed)
573        {
574            self.dependency
575                .outdated
576                .store(false, std::sync::atomic::Ordering::Relaxed);
577            *self.result.write().unwrap() = (self.formula.lock().unwrap())();
578        }
579        self.result.read().unwrap()
580    }
581}
582
583impl<T> Computation<T>
584where
585    T: Sync + Send + 'static,
586{
587    /// Create a new computation with the given formula and a static set of variables.
588    pub fn new<TVars>(
589        formula: impl for<'a> Fn(TVars::FunctorArgument<'a>) -> T + 'static + Send + Sync,
590        tvars: TVars,
591    ) -> Self
592    where
593        TVars: ComputationBuilder<T>,
594    {
595        let dependency = Dependency::new();
596
597        let formula = tvars.prepare(&dependency, formula);
598        let result = arc_rw_lock_new((formula)());
599        Self {
600            data: ComputationData::<T> {
601                result,
602                formula: arc_mutex_new(Box::new(formula)),
603                dependency,
604            },
605        }
606    }
607    /// Get the result of the computation. Re-compute it if outdated.
608    pub fn read_result<'a>(&'a self) -> impl Deref<Target = T> + 'a {
609        self.data.read_input()
610    }
611}
612
613// __     __         ____                            _        _   _
614// \ \   / /__  ___ / ___|___  _ __ ___  _ __  _   _| |_ __ _| |_(_) ___  _ __
615//  \ \ / / _ \/ __| |   / _ \| '_ ` _ \| '_ \| | | | __/ _` | __| |/ _ \| '_ \
616//   \ V /  __/ (__| |__| (_) | | | | | | |_) | |_| | || (_| | |_| | (_) | | | |
617//    \_/ \___|\___|\____\___/|_| |_| |_| .__/ \__,_|\__\__,_|\__|_|\___/|_| |_|
618//                                      |_|
619
620/// This trait is used to select the type of the function arguments, based on the computation type and the marker.
621/// Need to be public to use the VecComputation API, but should not be used directly.
622pub trait VecComputationFArgsSelectorTrait {
623    /// Function arguments
624    type FArgs<'a>;
625}
626
627/// This struct is used to select the type of the function arguments, based on the computation type and the marker.
628/// Need to be public to use the VecComputation API, but should not be used directly.
629pub struct VecComputationFArgsSelector<C, Marker> {
630    first_casper: PhantomData<C>,
631    second_casper: PhantomData<Marker>,
632}
633
634impl<C> VecComputationFArgsSelectorTrait for VecComputationFArgsSelector<C, DefaultVariableMarker>
635where
636    C: 'static,
637{
638    type FArgs<'a> = &'a C;
639}
640
641/// Markers for modifying the behavior of Computations.
642pub mod markers {
643    /// Marker to indicate that the arguments to a VecComputation are to be treaded as seperate variable.
644    #[derive(Debug)]
645    pub struct IndividualVariable {}
646
647    /// Marker to indicate that the arguments to a VecComputation are to be treaded as a group of variables in a tuple.
648    #[derive(Debug)]
649    pub struct GroupedVariables {}
650}
651
652/// Default Marker for arguments to vec computation.
653type DefaultVariableMarker = markers::IndividualVariable;
654
655type VecFnArg<'a, C, Marker> =
656    <VecComputationFArgsSelector<C, Marker> as VecComputationFArgsSelectorTrait>::FArgs<'a>;
657type VecFnArgs<'a, C, Marker> = Vec<VecFnArg<'a, C, Marker>>;
658
659struct VecComputationData<T, C, Marker>
660where
661    T: Send + Sync + 'static,
662    C: Send + Sync + 'static,
663    VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
664{
665    result: ArcRwLock<T>,
666    variables: ArcRwLock<LinkedHashMap<Key, Box<dyn VecInputReader<C, Marker>>>>,
667    formula: ArcMutex<Box<dyn for<'a> Fn(VecFnArgs<'a, C, Marker>) -> T + Send + Sync>>,
668    dependency: Arc<Dependency>,
669}
670
671impl<T, C, Marker> Debug for VecComputationData<T, C, Marker>
672where
673    T: Send + Sync + 'static + Debug,
674    C: Send + Sync + 'static + Debug,
675    VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
676{
677    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
678        f.debug_struct("")
679            .field("result", &self.result)
680            .field("dependency", &self.dependency)
681            .finish()
682    }
683}
684
685impl<T, C, Marker> Clone for VecComputationData<T, C, Marker>
686where
687    T: Send + Sync + 'static,
688    C: Send + Sync + 'static,
689    VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
690{
691    fn clone(&self) -> Self {
692        Self {
693            result: self.result.clone(),
694            variables: self.variables.clone(),
695            formula: self.formula.clone(),
696            dependency: self.dependency.clone(),
697        }
698    }
699}
700
701impl<T, C, Marker> InputReader<T> for VecComputationData<T, C, Marker>
702where
703    T: Sync + Send + 'static,
704    C: Send + Sync + 'static,
705    Marker: 'static,
706    VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
707{
708    type InputGuard<'a> = RwLockReadGuard<'a, T>;
709    fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
710        if self
711            .dependency
712            .outdated
713            .load(std::sync::atomic::Ordering::Relaxed)
714        {
715            self.dependency
716                .outdated
717                .store(false, std::sync::atomic::Ordering::Relaxed);
718            let variables = self.variables.read().unwrap();
719            let unlocked_vars: Vec<_> = variables.iter().map(|(_, v)| v.read_vec_input()).collect();
720            let values: VecFnArgs<'_, C, Marker> = unlocked_vars
721                .iter()
722                .map(|uv| -> VecFnArg<'_, C, Marker> { uv.as_input_value() })
723                .collect();
724            *self.result.write().unwrap() = (self.formula.lock().unwrap())(values);
725        }
726        self.result.read().unwrap()
727    }
728}
729
730/// A computation with a dynamic set of variables. Variables can be treated as single variable
731/// or as a group of variables.
732///
733/// ```rust
734/// # use compute_it::*;
735/// let v1 = Variable::<u32>::new(1);
736/// let v2 = Variable::<u32>::new(2);
737/// let v3 = Variable::<u32>::new(3);
738///
739/// // Create a new computation `c1` with `v1` and `v2` as initial set of variables.
740/// let mut c1 = VecComputation::<u32>::new(|v| v.into_iter().fold(0, |a, b| a + b), (&v1, &v2));
741/// println!("{} == 3", *c1.read_result());
742///
743/// // Add `v3` to the set of varibles.
744/// c1.push(&v3);
745/// println!("{} == 6", *c1.read_result());
746///
747/// // Remove `v2` to the set of varibles.
748/// c1.remove(&v2);
749/// println!("{} == 4", *c1.read_result());
750///
751/// // Change the value of `v1`
752/// v1.set(4);
753/// println!("{} == 7", *c1.read_result());
754/// ```
755///
756/// Example of a `VecComputation` with grouped variables:
757///
758/// ```rust
759/// # use compute_it::*;
760/// let v1: Variable<i32> = 0.into();
761/// let v2: Variable<u32> = 1.into();
762/// let v3: Variable<i32> = 2.into();
763///
764/// // Create a vec computation where the vector is made of a tuple of reference to i32 and u32 variables.
765/// let mut c1 = VecComputation::<i32, (i32, u32, i32), markers::GroupedVariables>::new(
766///     |v: Vec<(&i32, &u32, &i32)>| v.into_iter().fold(0, |a, (b, c, d)| a + b + *c as i32 + d),
767///     (&(&v1, &v2, &v3),),
768/// );
769/// ```
770#[derive(Debug)]
771pub struct VecComputation<T, C = T, Marker = DefaultVariableMarker>
772where
773    T: Send + Sync + 'static,
774    C: Send + Sync + 'static,
775    VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
776{
777    data: VecComputationData<T, C, Marker>,
778    casper: PhantomData<Marker>,
779}
780
781impl<T, C, Marker> ComputationValueType for VecComputation<T, C, Marker>
782where
783    T: Send + Sync + 'static,
784    C: Send + Sync + 'static,
785    VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
786{
787    type Type = T;
788}
789
790impl<T, C, Marker> ComputationInputInterface for VecComputation<T, C, Marker>
791where
792    T: Send + Sync + 'static,
793    C: Send + Sync + 'static,
794    VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait + 'static,
795{
796    type InputReaderType = VecComputationData<T, C, Marker>;
797    fn id(&self) -> Key {
798        self.data.dependency.key.clone()
799    }
800    fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>) {
801        (self.data.clone(), self.data.dependency.clone())
802    }
803}
804
805impl<T, C, Marker> VecComputation<T, C, Marker>
806where
807    T: Send + Sync + 'static,
808    C: Send + Sync + 'static,
809    Marker: 'static,
810    VecComputationFArgsSelector<C, Marker>: VecComputationFArgsSelectorTrait,
811{
812    /// Create a new computation with the given formula and an initial vector of variables.
813    pub fn new<TVars>(
814        formula: impl for<'a> Fn(VecFnArgs<'a, C, Marker>) -> T + 'static + Send + Sync,
815        tvars: TVars,
816    ) -> Self
817    where
818        TVars: ComputationVecBuilder<C, Marker>,
819    {
820        let dependency = Dependency::new();
821        let variables = tvars.prepare(&dependency);
822
823        let result = arc_rw_lock_new({
824            let unlocked_vars: Vec<_> = variables.iter().map(|(_, v)| v.read_vec_input()).collect();
825            let values: VecFnArgs<'_, C, Marker> = unlocked_vars
826                .iter()
827                .map(|uv| -> VecFnArg<'_, C, Marker> { uv.as_input_value() })
828                .collect();
829            (formula)(values)
830        });
831        let variables = arc_rw_lock_new(variables);
832
833        Self {
834            data: VecComputationData::<T, C, Marker> {
835                result,
836                variables,
837                formula: arc_mutex_new(Box::new(formula)),
838                dependency,
839            },
840            casper: Default::default(),
841        }
842    }
843    /// Get the result of the computation. Re-compute it if outdated.
844    pub fn read_result<'a>(&'a self) -> impl Deref<Target = T> + 'a {
845        self.data.read_input()
846    }
847    /// Push a new variable to the computation variable
848    pub fn push<CII>(&mut self, var: &CII)
849    where
850        CII: ComputationInputInterface<Type = C>,
851        <CII as ComputationInputInterface>::InputReaderType: VecInputReader<C, Marker>,
852    {
853        let (getter, dep) = var.prepare_value();
854        let id = dep.key.clone();
855        Dependency::link(&self.data.dependency, dep);
856        self.data
857            .variables
858            .write()
859            .unwrap()
860            .insert(id, Box::new(getter));
861        self.data.dependency.notify_all();
862    }
863    /// Remove a  variable from the computation variable
864    pub fn remove(&mut self, var: &impl ComputationInputInterface) {
865        let id = var.id();
866        self.data.variables.write().unwrap().remove(&id);
867        self.data.dependency.remove_dependency(&id);
868        self.data.dependency.notify_all();
869    }
870}
871
872impl<T, C> VecComputation<T, C>
873where
874    T: Default + std::ops::Add<Output = T> + Sync + Send,
875    C: Into<T> + Clone + Sync + Send,
876{
877    /// Create a VecComputation that computes the sum of the variables.
878    pub fn sum<TVars>(tvars: TVars) -> Self
879    where
880        TVars: ComputationVecBuilder<C, DefaultVariableMarker>,
881    {
882        Self::new(
883            |a| {
884                a.iter()
885                    .fold(T::default(), |a, b| a + <C as Into<T>>::into((**b).clone()))
886                    as T
887            },
888            tvars,
889        )
890    }
891}
892
893impl<T, C> VecComputation<T, C>
894where
895    T: Default + for<'a> std::ops::Add<&'a T, Output = T> + Sync + Send,
896    for<'a> &'a C: Into<&'a T>,
897    C: Sync + Send,
898{
899    /// Create a VecComputation that computes the sum of the variables.
900    pub fn sum_ref<TVars>(tvars: TVars) -> Self
901    where
902        TVars: ComputationVecBuilder<C, DefaultVariableMarker>,
903    {
904        Self::new(
905            |a| {
906                a.iter()
907                    .fold(T::default(), |a, b| a + <&C as Into<&T>>::into(*b)) as T
908            },
909            tvars,
910        )
911    }
912}
913impl<T, C> VecComputation<T, C>
914where
915    T: Default
916        + std::ops::Add<Output = T>
917        + TryFrom<usize>
918        + std::ops::Div<Output = T>
919        + Sync
920        + Send,
921    C: Into<T> + Clone + Sync + Send,
922    <T as TryFrom<usize>>::Error: Debug,
923{
924    /// Create a VecComputation that computes the average of the variables.
925    pub fn average<TVars>(tvars: TVars) -> Self
926    where
927        TVars: ComputationVecBuilder<C, DefaultVariableMarker>,
928    {
929        Self::new(
930            |a| {
931                a.iter()
932                    .fold(T::default(), |a, b| a + <C as Into<T>>::into((**b).clone()))
933                    / (<usize as TryInto<T>>::try_into(a.len()).expect("usize overflow"))
934            },
935            tvars,
936        )
937    }
938}
939
940// __     __         _       _     _
941// \ \   / /_ _ _ __(_) __ _| |__ | | ___
942//  \ \ / / _` | '__| |/ _` | '_ \| |/ _ \
943//   \ V / (_| | |  | | (_| | |_) | |  __/
944//    \_/ \__,_|_|  |_|\__,_|_.__/|_|\___|
945
946#[cfg(feature = "serde")]
947fn serde_dependency_new() -> Arc<Dependency> {
948    Dependency::new()
949}
950
951/// A variable. When the value is changed, it will update the computation.
952///
953/// Variable are created like this:
954///
955/// ```rust
956/// # use compute_it::*;
957/// let v1: Variable<i32> = 1.into();
958/// let v2 = Variable::<u32>::new(2);
959/// ```
960#[derive(Debug)]
961#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
962pub struct Variable<T>
963where
964    T: Send + Sync,
965{
966    t: ArcRwLock<T>,
967    #[cfg_attr(feature = "serde", serde(skip, default = "serde_dependency_new"))]
968    dependency: Arc<Dependency>,
969}
970
971impl<T> Default for Variable<T>
972where
973    T: Default + Send + Sync,
974{
975    fn default() -> Self {
976        Self {
977            t: ArcRwLock::<T>::default(),
978            dependency: Dependency::new(),
979        }
980    }
981}
982
983impl<T> From<T> for Variable<T>
984where
985    T: Send + Sync,
986{
987    fn from(value: T) -> Self {
988        Self::new(value)
989    }
990}
991
992impl<T> ComputationValueType for Variable<T>
993where
994    T: Send + Sync + 'static,
995{
996    type Type = T;
997}
998impl<T> ComputationInputInterface for Variable<T>
999where
1000    T: Send + Sync + 'static,
1001{
1002    type InputReaderType = ArcRwLock<T>;
1003    fn id(&self) -> Key {
1004        self.dependency.key.clone()
1005    }
1006    fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>) {
1007        (self.t.clone(), self.dependency.clone())
1008    }
1009}
1010
1011impl<T> Variable<T>
1012where
1013    T: Send + Sync,
1014{
1015    /// Create a new variable with a given default value.
1016    pub fn new(t: T) -> Self {
1017        Self {
1018            t: arc_rw_lock_new(t),
1019            dependency: Dependency::new(),
1020        }
1021    }
1022    /// Set the value of the variable.
1023    pub fn set(&self, t: T) {
1024        *self.t.write().unwrap() = t;
1025        self.dependency.notify_all();
1026    }
1027    /// Get the value as a ref (keep the value locked)
1028    pub fn read_value(&self) -> RwLockReadGuard<'_, T> {
1029        self.t.read().unwrap()
1030    }
1031    /// For uniformity with Computation
1032    fn read_result(&self) -> RwLockReadGuard<'_, T> {
1033        self.t.read().unwrap()
1034    }
1035    /// Get the inner locked value
1036    pub fn ro_value(&self) -> ccutils::sync::RoLock<T> {
1037        ccutils::sync::RoLock::new(&self.t)
1038    }
1039    /// Update the value. The function f receive a reference to the value.
1040    pub fn update(&self, f: impl Fn(&mut T)) {
1041        f(&mut self.t.write().unwrap());
1042        self.dependency.notify_all();
1043    }
1044}
1045
1046//  ____       __
1047// |  _ \ ___ / _| ___ _ __ ___ _ __   ___ ___
1048// | |_) / _ \ |_ / _ \ '__/ _ \ '_ \ / __/ _ \
1049// |  _ <  __/  _|  __/ | |  __/ | | | (_|  __/
1050// |_| \_\___|_|  \___|_|  \___|_| |_|\___\___|
1051
1052struct ReferenceData<T>
1053where
1054    T: Send + Sync + 'static,
1055{
1056    getter: ArcRwLock<Box<dyn VecInputReader<T, DefaultVariableMarker>>>,
1057    variable: Key,
1058    dependency: Arc<Dependency>,
1059}
1060
1061impl<T> Debug for ReferenceData<T>
1062where
1063    T: Debug + Sync + Send + 'static,
1064{
1065    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1066        f.debug_struct("")
1067            // .field("reference_value", &self.read_input())
1068            .finish()
1069    }
1070}
1071
1072impl<T> Clone for ReferenceData<T>
1073where
1074    T: Send + Sync + 'static,
1075{
1076    fn clone(&self) -> Self {
1077        Self {
1078            getter: self.getter.clone(),
1079            variable: self.variable.clone(),
1080            dependency: self.dependency.clone(),
1081        }
1082    }
1083}
1084
1085/// Reference to a Variable, Computation... Allows to change an input to a computation.
1086///
1087/// ```rust
1088/// # use compute_it::*;
1089///
1090/// let v1: Variable<i32> = 1.into();
1091/// let v2: Variable<i32> = 2.into();
1092///
1093/// let mut ref1 = Reference::<i32>::new(&v1);
1094///
1095/// // `c1` is initialized to use `v1` as input.
1096/// let c1 = Computation::<i32>::new(|(x,)| *x, (&ref1,));
1097/// println!("{} == 1", *c1.read_result());
1098///
1099/// // After this call `c1` will use `v2` as input.
1100/// ref1.replace(&v2);
1101/// println!("{} == 2", *c1.read_result());
1102/// ```
1103
1104#[derive(Debug)]
1105pub struct Reference<T>
1106where
1107    T: Send + Sync + 'static,
1108{
1109    data: ReferenceData<T>,
1110}
1111
1112impl<T> ComputationValueType for Reference<T>
1113where
1114    T: Send + Sync + 'static,
1115{
1116    type Type = T;
1117}
1118
1119impl<T> ComputationInputInterface for Reference<T>
1120where
1121    T: Send + Sync + 'static,
1122{
1123    type InputReaderType = ReferenceData<T>;
1124    fn id(&self) -> Key {
1125        self.data.dependency.key.clone()
1126    }
1127    fn prepare_value(&self) -> (Self::InputReaderType, Arc<Dependency>) {
1128        (self.data.clone(), self.data.dependency.clone())
1129    }
1130}
1131
1132#[ouroboros::self_referencing]
1133struct Whatever<T>
1134where
1135    T: 'static,
1136{
1137    lock: ArcRwLock<Box<dyn VecInputReader<T, DefaultVariableMarker>>>,
1138    #[covariant]
1139    #[borrows(lock)]
1140    getter: RwLockReadGuard<'this, Box<dyn VecInputReader<T, DefaultVariableMarker>>>,
1141    #[covariant]
1142    #[borrows(getter)]
1143    guard: Box<dyn VecInputGuard<T, DefaultVariableMarker> + 'this>,
1144}
1145
1146impl<'a, T> Deref for Whatever<T>
1147where
1148    T: Sync + Send + 'static,
1149{
1150    type Target = T;
1151    fn deref(&self) -> &Self::Target {
1152        self.borrow_guard().as_input_value()
1153        // .deref()
1154        // .as_input_value()
1155    }
1156}
1157
1158impl<T> InputReader<T> for ReferenceData<T>
1159where
1160    T: Sync + Send + 'static,
1161{
1162    type InputGuard<'a> = Whatever<T>;
1163    fn read_input<'a>(&'a self) -> Self::InputGuard<'a> {
1164        WhateverBuilder {
1165            lock: self.getter.clone(),
1166            getter_builder: |l| l.read().unwrap(),
1167            guard_builder: |l| l.read_vec_input(),
1168        }
1169        .build()
1170    }
1171}
1172
1173impl<T> Reference<T>
1174where
1175    T: Sync + Send + 'static,
1176{
1177    /// Create a new reference with the given formula.
1178    pub fn new<TVar>(tvar: &TVar) -> Self
1179    where
1180        TVar: ComputationInputInterface<Type = T>,
1181        for<'a> <<TVar as ComputationInputInterface>::InputReaderType as InputReader<T>>::InputGuard<'a>:
1182            Deref<Target = T>,
1183    {
1184        let dependency = Dependency::new();
1185        let (reader, dependent) = tvar.prepare_value();
1186        let variable = dependent.key.clone();
1187        Dependency::link(&dependency, dependent);
1188        Self {
1189            data: ReferenceData::<T> {
1190                getter: ccutils::sync::arc_rw_lock_new(Box::new(reader)),
1191                variable,
1192                dependency,
1193            },
1194        }
1195    }
1196    /// Get the result of the referenced variable.
1197    pub fn read_value<'a>(&'a self) -> impl Deref<Target = T> + 'a {
1198        self.data.read_input()
1199    }
1200    fn read_result<'a>(&'a self) -> impl Deref<Target = T> + 'a {
1201        self.data.read_input()
1202    }
1203    /// Replace the variable in the reference
1204    pub fn replace<TVar>(&mut self, tvar: &TVar)
1205    where
1206        TVar: ComputationInputInterface<Type = T>,
1207        for<'a> <<TVar as ComputationInputInterface>::InputReaderType as InputReader<T>>::InputGuard<'a>:
1208            Deref<Target = T>,
1209    {
1210        let (reader, dependent) = tvar.prepare_value();
1211        self.data.dependency.remove_dependency(&self.data.variable);
1212        self.data.variable = dependent.key.clone();
1213        Dependency::link(&self.data.dependency, dependent);
1214        *self.data.getter.write().unwrap() = Box::new(reader);
1215        self.data.dependency.notify_all();
1216    }
1217}
1218
1219//   ____                                 _               _____          _ _
1220//  / ___|___  _ __ ___  _ __   __ _ _ __(_)___  ___  _ _|_   _| __ __ _(_) |_ ___
1221// | |   / _ \| '_ ` _ \| '_ \ / _` | '__| / __|/ _ \| '_ \| || '__/ _` | | __/ __|
1222// | |__| (_) | | | | | | |_) | (_| | |  | \__ \ (_) | | | | || | | (_| | | |_\__ \
1223//  \____\___/|_| |_| |_| .__/ \__,_|_|  |_|___/\___/|_| |_|_||_|  \__,_|_|\__|___/
1224//                      |_|
1225
1226macro_rules! generate_traits_for_computation_getters {
1227    ($name:tt $(, extra: [$($extra_t: tt),+])? $(, blob: [$where_left:ty : $where_right: tt])?) => {
1228        impl<T $($(, $extra_t)+)?> PartialEq for $name<T $($(, $extra_t)+)?>
1229        where
1230            T: PartialEq + Send + Sync,
1231            $($($extra_t: Send + Sync + 'static,)+)?
1232            $($where_left: $where_right)?
1233        {
1234            fn eq(&self, other: &Self) -> bool {
1235                self.read_result().eq(&other.read_result())
1236            }
1237        }
1238
1239        impl<T $($(, $extra_t)+)?> PartialOrd for $name<T $($(, $extra_t)+)?>
1240        where
1241            T: PartialOrd + Send + Sync,
1242            $($($extra_t: Send + Sync + 'static,)+)?
1243            $($where_left: $where_right)?
1244        {
1245            fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
1246                self.read_result().partial_cmp(&other.read_result())
1247            }
1248        }
1249
1250        impl<T $($(, $extra_t)+)?> PartialEq<T> for $name<T $($(, $extra_t)+)?>
1251        where
1252            T: PartialEq + Send + Sync,
1253            $($($extra_t: Send + Sync + 'static,)+)?
1254            $($where_left: $where_right)?
1255        {
1256            fn eq(&self, other: &T) -> bool {
1257                self.read_result().eq(other)
1258            }
1259        }
1260
1261        impl<T $($(, $extra_t)+)?> PartialOrd<T> for $name<T  $($(, $extra_t)+)?>
1262        where
1263            T: PartialOrd + Send + Sync,
1264            $($($extra_t: Send + Sync + 'static,)+)?
1265            $($where_left: $where_right)?
1266        {
1267            fn partial_cmp(&self, other: &T) -> Option<std::cmp::Ordering> {
1268                self.read_result().partial_cmp(other)
1269            }
1270        }
1271    };
1272}
1273
1274generate_traits_for_computation_getters!(Computation);
1275generate_traits_for_computation_getters!(VecComputation, extra: [C, Marker], blob: [VecComputationFArgsSelector::<C, Marker>: VecComputationFArgsSelectorTrait]);
1276generate_traits_for_computation_getters!(Reference);
1277generate_traits_for_computation_getters!(Variable);
1278
1279//  _            _
1280// | |_ ___  ___| |_ ___
1281// | __/ _ \/ __| __/ __|
1282// | ||  __/\__ \ |_\__ \
1283//  \__\___||___/\__|___/
1284
1285#[cfg(test)]
1286mod tests {
1287    use super::*;
1288
1289    #[test]
1290    fn static_computation() {
1291        let v1 = Variable::<u32>::new(1);
1292        let v2 = Variable::<u32>::new(2);
1293        let v3 = Variable::<u32>::new(3);
1294
1295        let c1 = Computation::<u32>::new(|(a, b, c)| a + b + c, (&v1, &v2, &v3));
1296        assert_eq!(c1, 6);
1297
1298        v1.set(4);
1299        assert_eq!(c1, 9);
1300
1301        v3.update(|x| *x -= 3);
1302        assert_eq!(c1, 6);
1303    }
1304
1305    #[test]
1306    fn heterogenous_computation() {
1307        let v1 = Variable::<u16>::new(1);
1308        let v2 = Variable::<u32>::new(2);
1309        let v3 = Variable::<f32>::new(3.0);
1310
1311        let c1 = Computation::<f64>::new(
1312            |(a, b, c)| *a as f64 + *b as f64 + *c as f64,
1313            (&v1, &v2, &v3),
1314        );
1315        assert_eq!(c1, 6.0);
1316
1317        v1.set(4);
1318        assert_eq!(c1, 9.0);
1319
1320        v3.update(|x| *x -= 3.0);
1321        assert_eq!(c1, 6.0);
1322    }
1323
1324    #[test]
1325    fn intermediary_computation() {
1326        let v1 = Variable::<u16>::new(1);
1327        let v2 = Variable::<u32>::new(2);
1328        let v3 = Variable::<f32>::new(3.0);
1329
1330        let c1 = Computation::<f64>::new(
1331            |(a, b, c)| *a as f64 + *b as f64 + *c as f64,
1332            (&v1, &v2, &v3),
1333        );
1334        assert_eq!(c1, 6.0);
1335
1336        let v4 = Variable::<f64>::new(5.0);
1337
1338        let c2 = Computation::<f64>::new(|(a, b)| a + b, (&c1, &v4));
1339        assert_eq!(c2, 11.0);
1340
1341        v1.set(4);
1342        assert_eq!(c1, 9.0);
1343        assert_eq!(c2, 14.0);
1344
1345        v3.update(|x| *x -= 3.0);
1346        assert_eq!(c1, 6.0);
1347        assert_eq!(c2, 11.0);
1348
1349        v4.set(-1.0);
1350        assert_eq!(c1, 6.0);
1351        assert_eq!(c2, 5.0);
1352
1353        v1.set(0);
1354        assert_eq!(c2, 1.0);
1355    }
1356
1357    #[test]
1358    fn vec_computation() {
1359        let v1 = Variable::<u32>::new(1);
1360        let v2 = Variable::<u32>::new(2);
1361        let v3 = Variable::<u32>::new(3);
1362
1363        let mut c1 = VecComputation::<u32>::average(vec![&v1, &v2, &v3]);
1364        assert_eq!(c1, 2);
1365
1366        let v4 = Variable::<u32>::new(10);
1367        c1.push(&v4);
1368        assert_eq!(c1, 4);
1369        c1.remove(&v1);
1370        c1.remove(&v3);
1371        assert_eq!(c1, 6);
1372        v1.set(4);
1373        v3.set(2);
1374        assert_eq!(c1, 6);
1375        v4.set(2);
1376        assert_eq!(c1, 2);
1377        v2.set(0);
1378        assert_eq!(c1, 1);
1379
1380        let c2 = VecComputation::<u32>::sum(vec![&v1, &v2, &v3]);
1381        assert_eq!(c2, 6);
1382    }
1383
1384    #[test]
1385    fn vec_intermediary_computation() {
1386        let v1 = Variable::<u32>::new(1);
1387        let v2 = Variable::<u32>::new(2);
1388        let v3 = Variable::<u32>::new(3);
1389
1390        let mut c1 = VecComputation::<u32>::average(vec![&v1, &v2, &v3]);
1391        assert_eq!(c1, 2);
1392
1393        let v5 = Variable::<f32>::new(4.0);
1394        let c2 = Computation::<f32>::new(|(a, b)| *a as f32 + b, (&c1, &v5));
1395        assert_eq!(c2, 6.0);
1396
1397        let v6 = Variable::<f32>::new(2.0);
1398        let mut c3 = VecComputation::<f32>::sum((&c2, &v6));
1399
1400        let v4 = Variable::<u32>::new(10);
1401        c1.push(&v4);
1402        assert_eq!(c1, 4);
1403        assert_eq!(c2, 8.0);
1404        assert_eq!(c3, 10.0);
1405        c1.remove(&v1);
1406        c1.remove(&v3);
1407        assert_eq!(c1, 6);
1408        assert_eq!(c2, 10.0);
1409        assert_eq!(c3, 12.0);
1410        v1.set(4);
1411        v3.set(2);
1412        assert_eq!(c1, 6);
1413        assert_eq!(c2, 10.0);
1414        assert_eq!(c3, 12.0);
1415        v4.set(2);
1416        assert_eq!(c1, 2);
1417        assert_eq!(c2, 6.0);
1418        assert_eq!(c3, 8.0);
1419        v2.set(0);
1420        assert_eq!(c1, 1);
1421        assert_eq!(c2, 5.0);
1422        assert_eq!(c3, 7.0);
1423
1424        let v7 = Variable::<f32>::new(1.0);
1425        c3.push(&v7);
1426        assert_eq!(c1, 1);
1427        assert_eq!(c2, 5.0);
1428        assert_eq!(c3, 8.0);
1429        c3.remove(&v6);
1430        assert_eq!(c1, 1);
1431        assert_eq!(c2, 5.0);
1432        assert_eq!(c3, 6.0);
1433        c3.remove(&c2);
1434        assert_eq!(c1, 1);
1435        assert_eq!(c2, 5.0);
1436        assert_eq!(c3, 1.0);
1437    }
1438    #[test]
1439    fn test_traits() {
1440        let v1: Variable<i32> = 0.into();
1441        let v2: Variable<i32> = 1.into();
1442        let c1 = Computation::new(|(v1, v2)| *v1 + *v2, (&v1, &v2));
1443        let c2 = Computation::new(|(v1, v2)| *v1 - *v2, (&v1, &v2));
1444        let c3 = VecComputation::new(|v| *v[0] + *v[1], (&v1, &v2));
1445        let c4 = VecComputation::new(|v| *v[0] - *v[1], vec![&v1, &v2]);
1446        let c5 = VecComputation::new(|v| *v[0] - *v[1], (&v1, &v2));
1447        assert_eq!(c1, 1);
1448        assert_eq!(c2, -1);
1449        assert_eq!(c3, 1);
1450        assert_eq!(c4, -1);
1451        assert_eq!(c5, -1);
1452        assert!(v1 != v2);
1453        assert!(v1 < v2);
1454        assert!(c1 != c2);
1455        assert!(c1 > c2);
1456        assert!(c3 != c4);
1457        assert!(c3 > c4);
1458        assert!(c3 != c5);
1459        assert!(c3 > c5);
1460        assert!(c4 == c5);
1461    }
1462    #[test]
1463    fn test_vec_order() {
1464        let v1: Variable<i32> = 0.into();
1465        let v2: Variable<i32> = 1.into();
1466        let v3: Variable<i32> = 2.into();
1467        let v4: Variable<i32> = 3.into();
1468        let v5: Variable<i32> = 4.into();
1469        let v6: Variable<i32> = 5.into();
1470        let mut c1 = VecComputation::new(|v| v.windows(2).all(|w| w[0] < w[1]), (&v1, &v2));
1471        assert_eq!(c1, true);
1472        c1.push(&v3);
1473        c1.push(&v4);
1474        assert_eq!(c1, true);
1475        c1.remove(&v4);
1476        assert_eq!(c1, true);
1477        c1.push(&v5);
1478        assert_eq!(c1, true);
1479        c1.push(&v6);
1480        assert_eq!(c1, true);
1481        c1.remove(&v3);
1482        assert_eq!(c1, true);
1483        c1.remove(&v6);
1484        assert_eq!(c1, true);
1485        c1.push(&v4);
1486        assert_eq!(c1, false);
1487        c1.push(&v6);
1488        assert_eq!(c1, false);
1489        c1.remove(&v4);
1490        assert_eq!(c1, true);
1491    }
1492    #[test]
1493    fn test_tuples() {
1494        let v1: Variable<i32> = 0.into();
1495        let v2: Variable<i32> = 1.into();
1496        let v3: Variable<i32> = 2.into();
1497
1498        let mut c1 = VecComputation::<i32, (i32, i32, i32), markers::GroupedVariables>::new(
1499            |v: Vec<(&i32, &i32, &i32)>| v.into_iter().fold(0, |a, (b, c, d)| a + b + c + d),
1500            (&(&v1, &v2, &v3),),
1501        );
1502
1503        assert_eq!(c1, 3);
1504
1505        let v4: Variable<i32> = 3.into();
1506        let v5: Variable<i32> = 4.into();
1507        let v6: Variable<i32> = 5.into();
1508
1509        c1.push(&(&v4, &v5, &v6));
1510
1511        assert_eq!(c1, 15);
1512    }
1513    #[test]
1514    fn test_references() {
1515        let v1: Variable<i32> = 2.into();
1516        let v2: Variable<i32> = 1.into();
1517        let mut ref1 = Reference::<i32>::new(&v1);
1518        let c1 = Computation::<i32>::new(|(x,)| *x, (&ref1,));
1519        assert_eq!(c1, 2);
1520        v1.set(3);
1521        assert_eq!(c1, 3);
1522        ref1.replace(&v2);
1523        assert_eq!(c1, 1);
1524        v1.set(2);
1525        assert_eq!(ref1, 1);
1526        assert_eq!(c1, 1);
1527        v2.set(4);
1528        assert_eq!(ref1, 4);
1529        assert_eq!(c1, 4);
1530    }
1531}