fts_core/models/curve/pwl/
point.rs1use std::cmp::Ordering;
2
3#[derive(Clone, Debug, PartialEq)]
11#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema), schemars(inline))]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13pub struct Point {
14 pub rate: f64,
16 pub price: f64,
18}
19
20impl PartialOrd for Point {
24 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
25 let rate_ord = self.rate.partial_cmp(&other.rate)?;
26 let price_ord = self.price.partial_cmp(&other.price)?.reverse();
27 if rate_ord == Ordering::Equal {
30 Some(price_ord)
31 } else if price_ord == Ordering::Equal {
32 Some(rate_ord)
33 } else if rate_ord == price_ord {
34 Some(price_ord)
35 } else {
36 None
37 }
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 fn pt(x: f64, y: f64) -> Point {
46 Point { rate: x, price: y }
47 }
48
49 #[test]
50 fn test_good_cmp() {
51 let a = pt(0.0, 10.0);
52 let b = pt(10.0, 0.0);
53 assert!(a < b);
54 assert!(a <= b);
55 assert!(b > a);
56 assert!(b >= a);
57 assert!(a == a);
58 }
59
60 #[test]
61 fn test_bad_cmp() {
62 let a = pt(0.0, 10.0);
63 let b = pt(10.0, 20.0);
64 assert!(a.partial_cmp(&b).is_none());
65 assert!(b.partial_cmp(&a).is_none());
66 }
67
68 #[test]
69 fn test_nan() {
70 let a = pt(f64::NAN, 10.0);
71 let b = pt(10.0, f64::NAN);
72 assert!(a.partial_cmp(&b).is_none());
73 assert!(b.partial_cmp(&a).is_none());
74 }
75}