acme_tensor/shape/
rank.rs

1/*
2   Appellation: rank <mod>
3   Contrib: FL03 <jo3mccain@icloud.com>
4*/
5//! # Rank
6//!
7//! The rank of a n-dimensional array describes the number of dimensions
8use core::borrow::Borrow;
9use core::ops::{Deref, DerefMut, Not};
10use num::traits::{Num, One, Zero};
11#[cfg(feature = "serde")]
12use serde::{Deserialize, Serialize};
13
14pub trait IntoRank {
15    fn into_rank(self) -> Rank;
16}
17
18impl IntoRank for usize {
19    fn into_rank(self) -> Rank {
20        Rank::new(self)
21    }
22}
23
24#[cfg_attr(feature = "serde", derive(Deserialize, Serialize,))]
25#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
26pub struct Rank(pub(crate) usize);
27
28impl Rank {
29    pub fn new(rank: usize) -> Self {
30        Self(rank)
31    }
32
33    pub const fn scalar() -> Self {
34        Self(0)
35    }
36
37    pub fn into_inner(self) -> usize {
38        self.0
39    }
40
41    pub fn is_scalar(&self) -> bool {
42        self.0 == 0
43    }
44
45    pub fn rank(&self) -> usize {
46        self.0
47    }
48}
49
50impl std::fmt::Display for Rank {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        write!(f, "{}", self.0)
53    }
54}
55
56impl AsRef<usize> for Rank {
57    fn as_ref(&self) -> &usize {
58        &self.0
59    }
60}
61
62impl AsMut<usize> for Rank {
63    fn as_mut(&mut self) -> &mut usize {
64        &mut self.0
65    }
66}
67
68impl Borrow<usize> for Rank {
69    fn borrow(&self) -> &usize {
70        &self.0
71    }
72}
73
74impl Deref for Rank {
75    type Target = usize;
76
77    fn deref(&self) -> &Self::Target {
78        &self.0
79    }
80}
81
82impl DerefMut for Rank {
83    fn deref_mut(&mut self) -> &mut Self::Target {
84        &mut self.0
85    }
86}
87
88impl From<usize> for Rank {
89    fn from(rank: usize) -> Self {
90        Self(rank)
91    }
92}
93
94impl From<Rank> for usize {
95    fn from(rank: Rank) -> Self {
96        rank.0
97    }
98}
99
100unsafe impl Send for Rank {}
101
102unsafe impl Sync for Rank {}
103
104impl_partial_eq!(Rank -> 0: [usize]);
105
106macro_rules! impl_std_ops {
107    ($(($trait:tt, $method:ident, $e:tt)),*) => {
108        $(
109           impl_std_ops!($trait, $method, $e);
110        )*
111    };
112    ($trait:tt, $method:ident, $e:tt) => {
113        impl core::ops::$trait<usize> for Rank {
114            type Output = Rank;
115
116            fn $method(self, rhs: usize) -> Self::Output {
117                let rank = self.0 $e rhs;
118                Rank(rank)
119            }
120        }
121
122        impl<'a> core::ops::$trait<usize> for &'a Rank {
123            type Output = Rank;
124
125            fn $method(self, rhs: usize) -> Self::Output {
126                let rank = self.0 $e rhs;
127                Rank(rank)
128            }
129        }
130
131        impl core::ops::$trait for Rank {
132            type Output = Rank;
133
134            fn $method(self, rhs: Rank) -> Self::Output {
135                let rank = self.0 $e rhs.0;
136                Rank(rank)
137            }
138        }
139
140        impl<'a> core::ops::$trait<Rank> for &'a Rank {
141            type Output = Rank;
142
143            fn $method(self, rhs: Rank) -> Self::Output {
144                let rank = self.0 $e rhs.0;
145                Rank(rank)
146            }
147        }
148
149        impl<'a> core::ops::$trait<&'a Rank> for Rank {
150            type Output = Rank;
151
152            fn $method(self, rhs: &'a Rank) -> Self::Output {
153                let rank = self.0 $e rhs.0;
154                Rank(rank)
155            }
156        }
157
158        impl<'a> core::ops::$trait<&'a Rank> for &'a Rank {
159            type Output = Rank;
160
161            fn $method(self, rhs: &'a Rank) -> Self::Output {
162                let rank = self.0 $e rhs.0;
163                Rank(rank)
164            }
165        }
166    };
167}
168
169impl_std_ops!((Add, add, +), (Sub, sub, -), (Mul, mul, *), (Div, div, /), (Rem, rem, %));
170
171impl Not for Rank {
172    type Output = Rank;
173
174    fn not(self) -> Self::Output {
175        Rank(!self.0)
176    }
177}
178
179impl Num for Rank {
180    type FromStrRadixErr = <usize as Num>::FromStrRadixErr;
181
182    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
183        usize::from_str_radix(str, radix).map(Rank)
184    }
185}
186
187impl One for Rank {
188    fn one() -> Self {
189        Self(1)
190    }
191}
192
193impl Zero for Rank {
194    fn zero() -> Self {
195        Self(0)
196    }
197
198    fn is_zero(&self) -> bool {
199        self.0 == 0
200    }
201}