1use std::ops::{Deref, DerefMut, Index, IndexMut};
2
3#[macro_export]
13macro_rules! p_arr {
14 ($($x:expr),* $(,)?) => {{
15 $crate::PeriodicArray::new([$($x),*])
16 }};
17}
18
19#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
43#[cfg_attr(feature = "copy", derive(Copy))]
44#[repr(C)]
45pub struct PeriodicArray<T: Clone + Copy, const N: usize> {
46 pub(crate) inner: [T; N],
51}
52
53impl<T: Clone + Copy, const N: usize> PeriodicArray<T, N> {
54 #[inline(always)]
55 pub fn new(inner: [T; N]) -> Self {
56 PeriodicArray { inner }
57 }
58}
59
60impl<T: Clone + Copy, const N: usize> Index<usize> for PeriodicArray<T, N> {
61 type Output = T;
62 #[inline(always)]
63 fn index(&self, index: usize) -> &Self::Output {
64 unsafe { self.inner.get_unchecked(index % N) }
65 }
66}
67
68impl<T: Clone + Copy, const N: usize> IndexMut<usize> for PeriodicArray<T, N> {
69 #[inline(always)]
70 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
71 unsafe { self.inner.get_unchecked_mut(index % N) }
72 }
73}
74
75impl<T: Clone + Copy, const N: usize> Deref for PeriodicArray<T, N> {
76 type Target = [T; N];
77 #[inline(always)]
78 fn deref(&self) -> &Self::Target {
79 &self.inner
80 }
81}
82
83impl<T: Clone + Copy, const N: usize> DerefMut for PeriodicArray<T, N> {
84 #[inline(always)]
85 fn deref_mut(&mut self) -> &mut Self::Target {
86 &mut self.inner
87 }
88}
89
90impl<T: Clone + Copy, const N: usize> From<[T; N]> for PeriodicArray<T, N> {
91 #[inline(always)]
92 fn from(inner: [T; N]) -> Self {
93 PeriodicArray { inner }
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use crate::{p_arr, PeriodicArray};
100
101 #[test]
102 pub fn declare_with_macro() {
103 let pa_macro = p_arr![1, 2, 3];
104
105 let pa = PeriodicArray { inner: [1, 2, 3] };
106
107 assert_eq!(pa, pa_macro);
108 }
109
110 #[test]
111 pub fn index_into() {
112 let pa = p_arr![1, 2, 3];
113
114 assert_eq!(pa[0], 1);
116 assert_eq!(pa[1], 2);
117 assert_eq!(pa[2], 3);
118
119 assert_eq!(pa[3], 1);
121 assert_eq!(pa[4], 2);
122 assert_eq!(pa[5], 3);
123 }
124
125 #[test]
126 pub fn use_array_methods() {
127 let mut pa = p_arr![1, 2, 3];
128
129 let _x2 = pa.map(|x| x * x);
131
132 for x in pa.iter() {
134 let _ = x * x;
135 }
136 for p in pa.iter_mut() {
137 *p = *p * *p;
138 }
139 }
140}