1use crate::float::Float;
2use crate::value::Value01;
3use core::marker::PhantomData;
4use witnessed::Witnessed;
5
6pub fn metric(name: &'static str) -> MetricName {
12 MetricName { name }
13}
14
15pub struct MetricName {
17 name: &'static str,
18}
19
20impl MetricName {
21 pub fn measure(self) -> MeasureStage {
23 MeasureStage { name: self.name }
24 }
25}
26
27pub struct MeasureStage {
29 name: &'static str,
30}
31
32impl MeasureStage {
33 pub fn by<I, Raw, M>(self, measure: M) -> MeasureSet<I, Raw, M> {
35 MeasureSet {
36 name: self.name,
37 measure,
38 _phantom: PhantomData,
39 }
40 }
41}
42
43pub struct MeasureSet<I, Raw, M> {
45 name: &'static str,
46 measure: M,
47 _phantom: PhantomData<(I, Raw)>,
48}
49
50impl<I, Raw, M> MeasureSet<I, Raw, M> {
51 pub fn map01(self) -> Map01Stage<I, Raw, M> {
53 Map01Stage {
54 name: self.name,
55 measure: self.measure,
56 _phantom: PhantomData,
57 }
58 }
59}
60
61pub struct Map01Stage<I, Raw, M> {
63 name: &'static str,
64 measure: M,
65 _phantom: PhantomData<(I, Raw)>,
66}
67
68impl<I, Raw, M> Map01Stage<I, Raw, M> {
69 pub fn by<T: Float, F>(self, map01: F) -> Metric<T, I, Raw, M, F> {
73 Metric {
74 name: self.name,
75 measure: self.measure,
76 map01,
77 _phantom: PhantomData,
78 }
79 }
80}
81
82pub struct Metric<T, I, Raw, M, F> {
95 pub(crate) name: &'static str,
96 pub(crate) measure: M,
97 pub(crate) map01: F,
98 _phantom: PhantomData<(T, I, Raw)>,
99}
100
101impl<T: Float, I, Raw, M, F> Metric<T, I, Raw, M, F>
102where
103 M: Fn(&I) -> Raw,
104 F: Fn(&Raw, &I) -> Witnessed<T, Value01>,
105{
106 #[inline]
108 pub fn eval(&self, input: &I) -> Witnessed<T, Value01> {
109 let raw = (self.measure)(input);
110 (self.map01)(&raw, input)
111 }
112
113 #[inline]
115 pub fn name(&self) -> &str {
116 self.name
117 }
118}
119
120impl<T, I, Raw, M: Clone, F: Clone> Clone for Metric<T, I, Raw, M, F> {
122 fn clone(&self) -> Self {
123 Self {
124 name: self.name,
125 measure: self.measure.clone(),
126 map01: self.map01.clone(),
127 _phantom: PhantomData,
128 }
129 }
130}
131
132#[cfg(test)]
133mod tests_for_metric;