1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4#[derive(Debug, Clone, Copy, PartialEq)]
6pub struct Hypersphere<const N: usize> {
7 radius: f64,
8}
9
10impl<const N: usize> Hypersphere<N> {
11 #[must_use]
13 pub const fn new(radius: f64) -> Option<Self> {
14 if radius.is_finite() && radius > 0.0 {
15 Some(Self { radius })
16 } else {
17 None
18 }
19 }
20
21 #[must_use]
23 pub const fn dimension(self) -> usize {
24 N
25 }
26
27 #[must_use]
29 pub const fn ambient_dimension(self) -> usize {
30 N + 1
31 }
32
33 #[must_use]
35 pub const fn radius(self) -> f64 {
36 self.radius
37 }
38}
39
40pub type ThreeSphere = Hypersphere<3>;
42
43#[cfg(test)]
44mod tests {
45 use super::{Hypersphere, ThreeSphere};
46
47 #[test]
48 fn stores_hypersphere_metadata() {
49 let hypersphere = Hypersphere::<4>::new(2.0).expect("valid hypersphere");
50 let three_sphere = ThreeSphere::new(1.5).expect("valid 3-sphere");
51
52 assert_eq!(hypersphere.dimension(), 4);
53 assert_eq!(hypersphere.ambient_dimension(), 5);
54 assert_eq!(three_sphere.dimension(), 3);
55 assert_eq!(three_sphere.radius(), 1.5);
56 assert_eq!(Hypersphere::<2>::new(f64::NAN), None);
57 }
58}