progress_monitor/work/
numeric.rs1use std::{
2 fmt::Debug,
3 fmt::Display,
4 ops::{Add, Sub},
5};
6
7use num::{FromPrimitive, Num, ToPrimitive};
8
9use crate::work::{AddError, Work};
10
11pub trait NumReq: Num + ToPrimitive + FromPrimitive + PartialOrd + Debug + Display + Clone {}
12
13impl<T: Num + ToPrimitive + FromPrimitive + PartialOrd + Debug + Display + Clone> NumReq for T {}
14
15#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
16pub struct NumericWork<N: NumReq>(N);
17
18impl<N: NumReq> Work for NumericWork<N> {
19 type Type = N;
20
21 fn new<A: Into<Self::Type>>(value: A) -> Self {
22 Self(value.into())
23 }
24
25 fn zero() -> Self {
26 Self::new(N::zero())
27 }
28
29 fn min<'a>(a: &'a Self, b: &'a Self) -> &'a Self {
30 if a.0 < b.0 {
31 a
32 } else {
33 b
34 }
35 }
36
37 fn parent_work_done_when(
38 sub_work_done: Self,
39 of_total_sub_work: Self,
40 of_parent_work: Self,
41 ) -> Self {
42 let sub_work_done = sub_work_done.0.to_f64().expect("representable as f64");
43 let of_total_sub_work = of_total_sub_work.0.to_f64().expect("representable as f64");
44 let of_parent_work = of_parent_work.0.to_f64().expect("representable as f64");
45
46 let rel = sub_work_done / of_total_sub_work * of_parent_work;
47
48 Self::new(N::from_f64(rel).expect("cast from f64 to N"))
49 }
50}
51
52impl<N: NumReq> Display for NumericWork<N> {
53 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54 f.write_fmt(format_args!("{}", self.0))
55 }
56}
57
58impl<N: NumReq> Add for NumericWork<N> {
59 type Output = Result<Self, AddError>;
60
61 fn add(self, rhs: Self) -> Self::Output {
62 Ok(Self::new(self.0 + rhs.0))
63 }
64}
65
66impl<N: NumReq> Sub for NumericWork<N> {
67 type Output = Self;
68
69 fn sub(self, rhs: Self) -> Self::Output {
70 Self::new(self.0 - rhs.0)
71 }
72}
73
74impl<N: NumReq> From<N> for NumericWork<N> {
75 fn from(value: N) -> Self {
76 Self::new(value)
77 }
78}