use super::traits::IsRing;
pub fn wedge_sign<ZZ: IsRing>(p1: &ZZ, p2: &ZZ) -> i8 {
(p1.conj() * *p2).im_sign()
}
pub fn dot_sign<ZZ: IsRing>(p1: &ZZ, p2: &ZZ) -> i8 {
(p1.conj() * *p2).re_sign()
}
pub fn angle_between<ZZ: IsRing>(p: &ZZ, (a, b): (&ZZ, &ZZ)) -> bool {
wedge_sign(a, p) >= 0 && wedge_sign(p, b) >= 0
}
pub fn is_between<ZZ: IsRing>(p: &ZZ, (a, b): (&ZZ, &ZZ)) -> bool {
let v = *a - *p;
let w = *p - *b;
wedge_sign(&v, &w) == 0 && dot_sign(&v, &w) > 0
}
pub fn is_ccw<ZZ: IsRing>(p: &ZZ, (a, b): (&ZZ, &ZZ)) -> bool {
wedge_sign(&(*a - *p), &(*b - *p)) > 0
}
#[cfg(test)]
mod tests {
use num_traits::{One, Zero};
use super::super::rings::ZZ12;
use super::super::traits::{SymNum, Units};
use super::*;
type ZZi = ZZ12;
#[test]
fn test_is_between() {
let a: ZZi = ZZi::zero();
let b: ZZi = ZZi::one();
let c: ZZi = ZZi::from(2);
let e: ZZi = <ZZi as Units>::unit(ZZi::hturn() / 2);
let f: ZZi = b + e;
let g: ZZi = <ZZi as Units>::unit(1) + <ZZi as Units>::unit(-1) - ZZi::one();
assert!(is_between(&b, (&a, &c)));
assert!(is_between(&g, (&a, &b)));
assert!(!is_between(&b, (&a, &b)));
assert!(!is_between(&a, (&a, &b)));
assert!(!is_between(&c, (&a, &b)));
assert!(!is_between(&f, (&a, &b)));
}
#[test]
fn test_is_ccw() {
type ZZ = ZZ12;
assert!(is_ccw(
&ZZ::zero(),
(&<ZZ as Units>::unit(0), &<ZZ as Units>::unit(1))
));
assert!(is_ccw(
&ZZ::zero(),
(&<ZZ as Units>::unit(2), &<ZZ as Units>::unit(3))
));
assert!(!is_ccw(
&ZZ::zero(),
(&<ZZ as Units>::unit(0), &<ZZ as Units>::unit(0))
));
assert!(!is_ccw(
&ZZ::zero(),
(&<ZZ as Units>::unit(1), &<ZZ as Units>::unit(1))
));
assert!(!is_ccw(
&ZZ::zero(),
(&<ZZ as Units>::unit(1), &<ZZ as Units>::unit(0))
));
assert!(!is_ccw(
&ZZ::zero(),
(&<ZZ as Units>::unit(6), &<ZZ as Units>::unit(5))
));
}
#[test]
fn test_angle_between() {
type ZZ = ZZ12;
assert!(angle_between(
&<ZZ as Units>::unit(1),
(&<ZZ as Units>::unit(0), &<ZZ as Units>::unit(2))
));
assert!(angle_between(
&<ZZ as Units>::unit(-2),
(&<ZZ as Units>::unit(-3), &<ZZ as Units>::unit(1))
));
assert!(!angle_between(
&<ZZ as Units>::unit(1),
(&<ZZ as Units>::unit(-1), &<ZZ as Units>::unit(0))
));
assert!(angle_between(
&<ZZ as Units>::unit(1),
(&<ZZ as Units>::unit(1), &<ZZ as Units>::unit(2))
));
assert!(angle_between(
&<ZZ as Units>::unit(2),
(&<ZZ as Units>::unit(1), &<ZZ as Units>::unit(2))
));
}
}