#[cfg(feature = "img")]
pub mod ulamspiral_img;
#[cfg(feature = "prime")]
pub mod prime;
pub mod calc_coord;
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)]
pub enum Quad {
North,
NorthEast,
East,
SouthEast,
South,
SouthWest,
West,
NorthWest,
Center,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct UlamPoint {
pub value: u32,
pub quad: Quad,
pub is_prime: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct Coord {
pub x: i32,
pub y: i32,
}
impl Coord {
pub fn new(x: i32, y: i32) -> Coord {
Coord { x, y }
}
}
#[allow(clippy::comparison_chain)]
fn quad_of_coord(c: &Coord) -> Quad {
if c.x == 0 && c.y == 0 {
Quad::Center
} else if c.x >= 0 && c.y >= 0 {
if c.y > c.x {
Quad::North
} else if c.x > c.y {
Quad::East
} else {
Quad::NorthEast
}
} else if c.x <= 0 && c.y >= 0 {
if c.y > c.x.abs() {
Quad::North
} else if c.x.abs() > c.y {
Quad::West
} else {
Quad::NorthWest
}
}
else if c.x <= 0 && c.y <= 0 {
if c.y.abs() > c.x.abs() {
Quad::South
} else if c.x.abs() > c.y.abs() {
Quad::West
} else {
Quad::SouthWest
}
}
else if c.x >= 0 && c.y <= 0 {
if c.y.abs() > c.x {
Quad::South
} else if c.x > c.y.abs() {
Quad::East
} else {
Quad::SouthEast
}
} else {
Quad::Center
}
}
pub fn value_of_coord(c: &Coord) -> u32 {
let q = quad_of_coord(c);
match q {
Quad::North => (4 * (c.y * c.y) - c.y + (-c.x)).try_into().unwrap(),
Quad::East => (4 * (c.x * c.x) - (3 * c.x) + c.y).try_into().unwrap(),
Quad::South => (4 * (-c.y * -c.y) + (3 * -c.y) + c.x) as u32,
Quad::West => (4 * (-c.x * -c.x) + (-c.x) + (-c.y)) as u32,
Quad::NorthWest => (4 * (c.x * c.x)) as u32,
Quad::NorthEast => (4 * (c.x * c.x) - 2 * c.x) as u32,
Quad::SouthWest => (4 * (c.x * c.x) + 2 * c.x.abs()) as u32,
Quad::SouthEast => (4 * (c.x * c.x) + 4 * c.x) as u32,
Quad::Center => 0,
}
}
pub fn value_of_xy(x: i32, y: i32) -> u32 {
let c = Coord { x, y };
let q = quad_of_coord(&c);
match q {
Quad::North => (4 * (c.y * c.y) - c.y + (-c.x)).try_into().unwrap(),
Quad::East => (4 * (c.x * c.x) - (3 * c.x) + c.y).try_into().unwrap(),
Quad::South => (4 * (-c.y * -c.y) + (3 * -c.y) + c.x) as u32,
Quad::West => (4 * (-c.x * -c.x) + (-c.x) + (-c.y)) as u32,
Quad::NorthWest => (4 * (c.x * c.x)) as u32,
Quad::NorthEast => (4 * (c.x * c.x) - 2 * c.x) as u32,
Quad::SouthWest => (4 * (c.x * c.x) + 2 * c.x.abs()) as u32,
Quad::SouthEast => (4 * (c.x * c.x) + 4 * c.x) as u32,
Quad::Center => 0,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_n_val() {
let c1 = Coord::new(-9, 10);
let result = value_of_coord(&c1);
assert_eq!(result, 399);
}
#[test]
fn check_w_val() {
let c1 = Coord::new(-6, -3);
let result = value_of_coord(&c1);
assert_eq!(result, 153);
}
#[test]
fn check_e_val() {
let c1 = Coord::new(8, -2);
let result = value_of_coord(&c1);
assert_eq!(result, 230);
}
#[test]
fn check_s_val() {
let c1 = Coord::new(0, -2);
let result = value_of_coord(&c1);
assert_eq!(result, 22);
}
#[test]
fn check_se_val() {
let c1 = Coord::new(9, -9);
let result = value_of_coord(&c1);
dbg!(result);
assert_eq!(result, 360);
}
#[test]
fn check_ne_val() {
let c1 = Coord::new(2, 2);
let result = value_of_coord(&c1);
assert_eq!(result, 12);
}
#[test]
fn check_nw_val() {
let c1 = Coord::new(-3, 3);
let result = value_of_coord(&c1);
assert_eq!(result, 36);
}
#[test]
fn check_sw_val() {
let c1 = Coord::new(-9, -9);
let result = value_of_coord(&c1);
assert_eq!(result, 342);
}
#[test]
fn check_e_val_big() {
let c1 = Coord::new(400, -221);
let result = value_of_coord(&c1);
dbg!(result);
assert_eq!(result, 638579);
}
#[test]
fn check_w_val_big() {
let c1 = Coord::new(-398, -129);
let result = value_of_coord(&c1);
assert_eq!(result, 634143);
}
#[test]
fn check_s_val_big() {
let c1 = Coord::new(-397, -996);
let result = value_of_coord(&c1);
assert_eq!(result, 3970655);
}
#[test]
fn check_n_val_big() {
let c1 = Coord::new(250, 999);
let result = value_of_coord(&c1);
assert_eq!(result, 3990755);
}
}