/ src / curve / split_quad.rs
split_quad.rs
 1  #![allow(missing_docs)]
 2  #![allow(dead_code)]
 3  
 4  use arrayvec::ArrayVec;
 5  
 6  use super::Quadratic;
 7  
 8  pub struct SplitQuadPart {
 9      quad: Quadratic,
10      until: f64,
11  }
12  
13  pub struct SplitQuad {
14      quads: ArrayVec<SplitQuadPart, 3>,
15  }
16  
17  impl SplitQuad {
18      pub fn single(q: Quadratic) -> Self {
19          Self {
20              quads: [SplitQuadPart {
21                  quad: q,
22                  until: f64::INFINITY,
23              }]
24              .into_iter()
25              .collect(),
26          }
27      }
28  }
29  
30  pub struct QuadBound {
31      upper: SplitQuad,
32      lower: SplitQuad,
33  }
34  
35  impl QuadBound {
36      pub fn new(mut q: Quadratic, upper: f64, lower: f64, shift: f64) -> Self {
37          debug_assert!(lower <= 0.0 && 0.0 <= upper);
38          debug_assert!(shift >= 0.0);
39          let center = -q.c1 / (2.0 * q.c0);
40          let extremum = q.c0 + q.c1 * center;
41          if center.is_infinite() || extremum.is_infinite() {
42              // Our quad is close enough to linear.
43              q.c2 = 0.0;
44              let upper = q + upper;
45              let lower = q + lower;
46  
47              let signed_shift = if q.c1 > 0.0 { shift } else { -shift };
48  
49              Self {
50                  upper: SplitQuad::single(upper.shift(-signed_shift)),
51                  lower: SplitQuad::single(lower.shift(signed_shift)),
52              }
53          } else {
54              todo!()
55          }
56      }
57  }