use super::super::FloatType;
#[derive(Debug, PartialEq)]
pub enum Roots<F: FloatType> {
No([F; 0]),
One([F; 1]),
Two([F; 2]),
Three([F; 3]),
Four([F; 4]),
}
impl<F: FloatType> AsRef<[F]> for Roots<F> {
fn as_ref(&self) -> &[F] {
match self {
&Roots::No(ref x) => x,
&Roots::One(ref x) => x,
&Roots::Two(ref x) => x,
&Roots::Three(ref x) => x,
&Roots::Four(ref x) => x,
}
}
}
impl<F: FloatType> Roots<F> {
fn check_new_root(&self, new_root: F) -> (bool, usize) {
let mut pos = 0;
let mut exists = false;
for x in self.as_ref().iter() {
if *x == new_root {
exists = true;
break;
}
if *x > new_root {
break;
}
pos = pos + 1;
}
(exists, pos)
}
pub fn add_new_root(self, new_root: F) -> Self {
match self {
Roots::No(_) => Roots::One([new_root]),
_ => {
let (exists, pos) = self.check_new_root(new_root);
if exists {
self
} else {
let old_roots = self.as_ref();
match (old_roots.len(), pos) {
(1, 0) => Roots::Two([new_root, old_roots[0]]),
(1, 1) => Roots::Two([old_roots[0], new_root]),
(2, 0) => Roots::Three([new_root, old_roots[0], old_roots[1]]),
(2, 1) => Roots::Three([old_roots[0], new_root, old_roots[1]]),
(2, 2) => Roots::Three([old_roots[0], old_roots[1], new_root]),
(3, 0) => Roots::Four([new_root, old_roots[0], old_roots[1], old_roots[2]]),
(3, 1) => Roots::Four([old_roots[0], new_root, old_roots[1], old_roots[2]]),
(3, 2) => Roots::Four([old_roots[0], old_roots[1], new_root, old_roots[2]]),
(3, 3) => Roots::Four([old_roots[0], old_roots[1], old_roots[2], new_root]),
_ => panic!("Cannot add root"),
}
}
}
}
}
}
#[test]
fn test_roots() {
let mut roots = Roots::One([1f32]);
assert_eq!(roots, Roots::One([1f32]));
roots = roots.add_new_root(1f32);
assert_eq!(roots, Roots::One([1f32]));
roots = roots.add_new_root(0f32);
assert_eq!(roots, Roots::Two([0f32, 1f32]));
roots = roots.add_new_root(0f32);
assert_eq!(roots, Roots::Two([0f32, 1f32]));
roots = roots.add_new_root(3f32);
assert_eq!(roots, Roots::Three([0f32, 1f32, 3f32]));
roots = roots.add_new_root(2f32);
assert_eq!(roots, Roots::Four([0f32, 1f32, 2f32, 3f32]));
}