Skip to main content

use_configuration/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use use_incidence::IncidenceStructure;
5
6/// Basic point-line configuration metadata.
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct GeometricConfiguration {
9    point_count: usize,
10    line_count: usize,
11    incidence_count: usize,
12}
13
14impl GeometricConfiguration {
15    /// Creates a configuration descriptor with positive point and line counts.
16    #[must_use]
17    pub const fn new(
18        point_count: usize,
19        line_count: usize,
20        incidence_count: usize,
21    ) -> Option<Self> {
22        if point_count > 0 && line_count > 0 {
23            Some(Self {
24                point_count,
25                line_count,
26                incidence_count,
27            })
28        } else {
29            None
30        }
31    }
32
33    /// Returns the point count.
34    #[must_use]
35    pub const fn point_count(self) -> usize {
36        self.point_count
37    }
38
39    /// Returns the line count.
40    #[must_use]
41    pub const fn line_count(self) -> usize {
42        self.line_count
43    }
44
45    /// Returns the incidence count.
46    #[must_use]
47    pub const fn incidence_count(self) -> usize {
48        self.incidence_count
49    }
50}
51
52/// Two rows of six labels used in double-six configurations.
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub struct DoubleSix {
55    first: [usize; 6],
56    second: [usize; 6],
57}
58
59impl DoubleSix {
60    /// Creates a double-six label arrangement.
61    #[must_use]
62    pub const fn new(first: [usize; 6], second: [usize; 6]) -> Self {
63        Self { first, second }
64    }
65
66    /// Returns the standard label arrangement.
67    #[must_use]
68    pub const fn standard() -> Self {
69        Self::new([0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11])
70    }
71
72    /// Returns the first row of labels.
73    #[must_use]
74    pub const fn first(self) -> [usize; 6] {
75        self.first
76    }
77
78    /// Returns the second row of labels.
79    #[must_use]
80    pub const fn second(self) -> [usize; 6] {
81        self.second
82    }
83
84    /// Returns the paired line count.
85    #[must_use]
86    pub const fn pair_count(self) -> usize {
87        6
88    }
89}
90
91/// The Schlafli double-six configuration metadata.
92#[derive(Debug, Clone, Copy, PartialEq, Eq)]
93pub struct SchlafliDoubleSix {
94    arrangement: DoubleSix,
95    configuration: GeometricConfiguration,
96}
97
98impl SchlafliDoubleSix {
99    /// Creates the standard Schlafli double-six metadata record.
100    #[must_use]
101    pub const fn new() -> Self {
102        Self {
103            arrangement: DoubleSix::standard(),
104            configuration: GeometricConfiguration {
105                point_count: 12,
106                line_count: 30,
107                incidence_count: 60,
108            },
109        }
110    }
111
112    /// Returns the double-six label arrangement.
113    #[must_use]
114    pub const fn arrangement(self) -> DoubleSix {
115        self.arrangement
116    }
117
118    /// Returns the point-line configuration counts.
119    #[must_use]
120    pub const fn configuration(self) -> GeometricConfiguration {
121        self.configuration
122    }
123
124    /// Returns a sparse incidence structure carrying the standard counts.
125    #[must_use]
126    pub fn incidence_structure(self) -> IncidenceStructure {
127        IncidenceStructure::new(
128            self.configuration.point_count(),
129            self.configuration.line_count(),
130            Vec::new(),
131        )
132        .expect("standard double-six counts are positive")
133    }
134}
135
136impl Default for SchlafliDoubleSix {
137    fn default() -> Self {
138        Self::new()
139    }
140}
141
142#[cfg(test)]
143mod tests {
144    use super::{DoubleSix, GeometricConfiguration, SchlafliDoubleSix};
145
146    #[test]
147    fn stores_schlafli_double_six_metadata() {
148        let double_six = SchlafliDoubleSix::new();
149        let structure = double_six.incidence_structure();
150
151        assert_eq!(double_six.arrangement().pair_count(), 6);
152        assert_eq!(double_six.configuration().point_count(), 12);
153        assert_eq!(structure.line_count(), 30);
154        assert_eq!(DoubleSix::standard().first(), [0, 1, 2, 3, 4, 5]);
155        assert_eq!(GeometricConfiguration::new(0, 1, 0), None);
156    }
157}