Skip to main content

use_schlafli/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use core::fmt;
5
6/// A Schlafli symbol represented by its numeric entries.
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct SchlafliSymbol {
9    entries: Vec<usize>,
10}
11
12impl SchlafliSymbol {
13    /// Creates a symbol from positive entries.
14    #[must_use]
15    pub fn new(entries: Vec<usize>) -> Option<Self> {
16        if !entries.is_empty() && entries.iter().all(|entry| *entry >= 2) {
17            Some(Self { entries })
18        } else {
19            None
20        }
21    }
22
23    /// Creates a regular polygon symbol `{p}`.
24    #[must_use]
25    pub fn polygon(p: usize) -> Option<Self> {
26        if p >= 3 { Self::new(vec![p]) } else { None }
27    }
28
29    /// Creates a regular polyhedron symbol `{p, q}`.
30    #[must_use]
31    pub fn polyhedron(p: usize, q: usize) -> Option<Self> {
32        if p >= 3 && q >= 3 {
33            Self::new(vec![p, q])
34        } else {
35            None
36        }
37    }
38
39    /// Creates a regular polychoron symbol `{p, q, r}`.
40    #[must_use]
41    pub fn polychoron(p: usize, q: usize, r: usize) -> Option<Self> {
42        if p >= 3 && q >= 3 && r >= 3 {
43            Self::new(vec![p, q, r])
44        } else {
45            None
46        }
47    }
48
49    /// Returns the symbol entries.
50    #[must_use]
51    pub fn entries(&self) -> &[usize] {
52        &self.entries
53    }
54
55    /// Returns the Coxeter rank conventionally associated with this symbol.
56    #[must_use]
57    pub fn rank(&self) -> usize {
58        self.entries.len() + 1
59    }
60
61    /// Returns the regular polytope dimension conventionally associated with this symbol.
62    #[must_use]
63    pub fn dimension(&self) -> usize {
64        self.entries.len()
65    }
66}
67
68impl fmt::Display for SchlafliSymbol {
69    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
70        formatter.write_str("{")?;
71
72        for (index, entry) in self.entries.iter().enumerate() {
73            if index > 0 {
74                formatter.write_str(", ")?;
75            }
76
77            write!(formatter, "{entry}")?;
78        }
79
80        formatter.write_str("}")
81    }
82}
83
84#[cfg(test)]
85mod tests {
86    use super::SchlafliSymbol;
87
88    #[test]
89    fn formats_schlafli_symbols() {
90        let symbol = SchlafliSymbol::polychoron(3, 4, 3).expect("valid symbol");
91
92        assert_eq!(symbol.entries(), &[3, 4, 3]);
93        assert_eq!(symbol.rank(), 4);
94        assert_eq!(symbol.dimension(), 3);
95        assert_eq!(symbol.to_string(), "{3, 4, 3}");
96        assert_eq!(SchlafliSymbol::polygon(2), None);
97    }
98}