File size: 1,683 Bytes
224e773 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | //! QLG Sphere: Canonical six-point integer geometry
//!
//! S_can = {x ∈ Z³ : x₀² + x₁² + x₂² = 1}
//! Solutions: {(±1,0,0), (0,±1,0), (0,0,±1)}
use crate::Point;
/// Verify membership in canonical sphere.
pub fn is_on_sphere(p: &Point) -> bool {
p.0 * p.0 + p.1 * p.1 + p.2 * p.2 == 1
}
/// All six canonical points
pub fn canonical_points() -> [Point; 6] {
[
Point(1, 0, 0),
Point(-1, 0, 0),
Point(0, 1, 0),
Point(0, -1, 0),
Point(0, 0, 1),
Point(0, 0, -1),
]
}
/// Encode point to 3-byte array (little-endian signed integers)
pub fn encode(p: &Point) -> [u8; 3] {
[
(p.0 as i8) as u8,
(p.1 as i8) as u8,
(p.2 as i8) as u8,
]
}
/// Decode point from 3-byte array
pub fn decode(bytes: &[u8; 3]) -> Point {
Point(
bytes[0] as i8 as i32,
bytes[1] as i8 as i32,
bytes[2] as i8 as i32,
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn canonical_on_sphere() {
for p in canonical_points() {
assert!(is_on_sphere(&p));
}
}
#[test]
fn six_solutions() {
assert_eq!(canonical_points().len(), 6);
}
#[test]
fn round_trip() {
for p in canonical_points() {
let encoded = encode(&p);
let decoded = decode(&encoded);
assert_eq!(p, decoded);
}
}
#[test]
fn invalid_rejected() {
assert!(!is_on_sphere(&Point(1, 1, 0)));
assert!(!is_on_sphere(&Point(2, 0, 0)));
assert!(!is_on_sphere(&Point(0, 0, 0)));
}
}
|