use std::ops::Index;
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy, Hash)]
pub struct Improper {
data: [usize; 4],
}
impl Improper {
#[must_use]
pub fn new(i: usize, j: usize, k: usize, m: usize) -> Self {
assert!(
!(j == i || j == k || j == m),
"cannot have an atom linked to itself in an improper dihedral angle"
);
assert!(
!(i == k || i == m || k == m),
"cannot have an atom twice in an improper dihedral angle"
);
let mut others = [i, k, m];
others.sort_unstable();
Improper {
data: [others[0], j, others[1], others[2]],
}
}
}
impl Index<usize> for Improper {
type Output = usize;
fn index(&self, index: usize) -> &Self::Output {
assert!(index < 4, "can not access atom n° {index} in dihedral");
&self.data[index]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_improper_creation() {
let improper = Improper::new(5, 1, 8, 3);
assert_eq!(improper[0], 3); assert_eq!(improper[1], 1); assert_eq!(improper[2], 5); assert_eq!(improper[3], 8); }
#[test]
fn test_improper_equality() {
let improper1 = Improper::new(5, 1, 8, 3);
let improper2 = Improper::new(3, 1, 5, 8);
let improper3 = Improper::new(8, 1, 3, 5);
assert_eq!(improper1, improper2);
assert_eq!(improper1, improper3);
assert_eq!(improper2, improper3);
let improper4 = Improper::new(5, 2, 8, 3);
assert_ne!(improper1, improper4);
}
#[test]
#[should_panic(expected = "cannot have an atom linked to itself in an improper dihedral angle")]
fn test_improper_with_duplicate_central() {
let _ = Improper::new(1, 2, 2, 3);
}
#[test]
#[should_panic(expected = "cannot have an atom twice in an improper dihedral angle")]
fn test_improper_with_duplicate_outer() {
let _ = Improper::new(1, 2, 1, 3);
}
#[test]
#[should_panic(expected = "can not access atom n° 4 in dihedral")]
fn test_improper_index_out_of_bounds() {
let improper = Improper::new(5, 1, 8, 3);
let _ = improper[4]; }
}