use crate::zzbase::ZZNum;
pub fn revcomp(angles: &[i8]) -> Vec<i8> {
angles.iter().rev().map(|a| -a).collect()
}
pub fn unit_idx<T: ZZNum>(angle: i8) -> i8 {
let a = normalize_angle::<T>(angle);
let half = T::hturn();
if a == 0 {
return 1;
}
if a == half {
return -1;
}
if a > 0 {
return a + 1;
}
return -(half + a) - 1;
}
pub fn to_abs_seq<T: ZZNum>(angles: &[i8]) -> Vec<i8> {
let mut currdir: i8 = 0;
let mut result: Vec<i8> = Vec::new();
for a in angles {
currdir = currdir + a;
result.push(unit_idx::<T>(currdir));
}
result
}
pub fn normalize_angle<T: ZZNum>(angle: i8) -> i8 {
let a = angle % T::turn();
if a.abs() <= T::hturn() {
a
} else {
-(a.signum() * T::turn() - a)
}
}
pub fn upscale_angles<T: ZZNum>(src_ring: i8, angles: &[i8]) -> Vec<i8> {
assert_eq!(T::zz_params().full_turn_steps % src_ring, 0);
let scale = T::zz_params().full_turn_steps / src_ring;
angles.iter().map(|x| x * scale).collect()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::zz::{ZZ12, ZZ24, ZZ6};
use crate::zzbase::ZZBase;
#[test]
fn test_revcomp() {
assert_eq!(revcomp(vec![].as_slice()), vec![]);
assert_eq!(revcomp(vec![6].as_slice()), vec![-6]);
let v = vec![1, 3, -2, 4];
assert_eq!(revcomp(v.as_slice()), vec![-4, 2, -3, -1]);
assert_eq!(revcomp(revcomp(v.as_slice()).as_slice()).as_slice(), v);
}
#[test]
fn test_abs_seq() {
assert_eq!(
to_abs_seq::<ZZ12>(&[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]),
&[1, 1, 2, 3, 4, 5, 6, -1, -2, -3, -4, -5, -6, 1]
);
assert_eq!(
to_abs_seq::<ZZ12>(&[0, 4, 2, 1, -3, -5]),
&[1, 5, -1, -2, 5, -6]
);
}
#[test]
fn test_normalize_angles() {
assert_eq!(normalize_angle::<ZZ12>(0), 0);
assert_eq!(normalize_angle::<ZZ12>(1), 1);
assert_eq!(normalize_angle::<ZZ12>(-1), -1);
assert_eq!(normalize_angle::<ZZ12>(5), 5);
assert_eq!(normalize_angle::<ZZ12>(-5), -5);
assert_eq!(normalize_angle::<ZZ12>(6), 6);
assert_eq!(normalize_angle::<ZZ12>(-6), -6);
assert_eq!(normalize_angle::<ZZ12>(7), -5);
assert_eq!(normalize_angle::<ZZ12>(-7), 5);
assert_eq!(normalize_angle::<ZZ12>(11), -1);
assert_eq!(normalize_angle::<ZZ12>(-11), 1);
assert_eq!(normalize_angle::<ZZ12>(12), 0);
assert_eq!(normalize_angle::<ZZ12>(-12), 0);
assert_eq!(normalize_angle::<ZZ12>(13), 1);
assert_eq!(normalize_angle::<ZZ12>(-13), -1);
}
#[test]
fn test_upscale_angles() {
let exp: &[i8] = &[-4, 8, 12];
assert_eq!(upscale_angles::<ZZ24>(ZZ6::turn(), &[-1, 2, 3]), exp);
}
}