numera/number/integer/nnz/
sized.rs

1// numera::number::integer::nnz::sized
2//
3//!
4//
5// TOC
6//
7// - macro
8//   - define_non_negative_integer_sized
9// - definitions
10//   - NonNegativeInteger[8|16|32|64|128]
11
12#[cfg(feature = "try_from")]
13use crate::number::integer::NonNegativeIntegers;
14use crate::{
15    error::{IntegerErrors, NumeraResult},
16    number::{
17        macros::impl_larger_smaller,
18        traits::{
19            Bound, ConstLowerBounded, ConstOne, ConstUpperBounded, ConstZero, Count, Countable,
20            Ident, LowerBounded, NonNegative, Number, One, Positive, Sign, UpperBounded, Zero,
21        },
22    },
23};
24use core::fmt;
25use devela::paste;
26
27/* macro */
28
29/// # What it does
30/// - defines an Integer of a concrete size.
31/// - implements Number: Bound + Count + Ident + Sign
32/// - implements Default → 0
33///
34/// # Args
35/// - `$name`: the base name of the integer. E.g. `NonNegaiveInteger`.
36/// - `$abbr`: the base abbreviated name, E.g. `Nnz`.
37/// - `$p`: the primitive prefix (i or u).
38///
39/// - `$doc_num`: the type of number.
40/// - `$doc_type`: adds to the type doc-comment.
41// - `$doc_new`: adds to the `new` constructor doc-comment.
42///
43/// - `$doc_sign`: an optional negative sign
44/// - `$doc_lower`: the lower bound of the number type.
45/// - `$doc_upper`: the upper bound of the number type.
46///
47/// - `$doc_det`: the determinant before the bit size. e.g. "An" (8-bit) or "A" 16-bit.
48/// - `$b`: the size in bits of the primitive used.
49macro_rules! define_nonnegative_integer_sized {
50    // defines multiple integer types, with an inner primitive.
51    (multi $name:ident, $abbr:ident, $p:ident,
52     $doc_num:literal, $doc_type:literal, // $doc_new:literal,
53     $doc_sign:literal, $doc_lower:expr, $doc_upper:expr,
54        $(
55            (
56             $doc_det:literal, $b:expr,
57             larger: $larger:literal, $larger_b:literal,
58             smaller: $smaller:literal, $smaller_b:literal
59            )
60        ),+
61     ) => {
62        $(
63            define_nonnegative_integer_sized![single $name, $abbr, $p,
64               $doc_num, $doc_type, // $doc_new,
65               $doc_sign, $doc_lower, $doc_upper,
66               ($doc_det, $b,
67                larger: $larger, $larger_b,
68                smaller: $smaller, $smaller_b
69               )];
70        )+
71    };
72    // defines a single integer type, with an inner primitive.
73    (single $name:ident, $abbr:ident, $p:ident,
74     $doc_num:literal, $doc_type:literal, // $doc_new:literal,
75     $doc_sign:literal, $doc_lower:expr, $doc_upper:expr,
76     (
77      $doc_det:literal, $b:expr,
78      larger: $larger:literal, $larger_b:literal,
79      smaller: $smaller:literal, $smaller_b:literal
80     )
81    ) => { paste! {
82        #[doc = $doc_det " "$b "-bit " $doc_num $doc_type ","]
83        #[doc = "also known as [`" [<$abbr$b>] "`][super::" [<$abbr$b>] "]."]
84        #[doc = "\n\nThe range of valid numeric values is $\\lbrack"
85        $doc_sign 0 " \\dots$ [`"
86        $p$b "::" $doc_upper "`]$\\rbrack$."]
87        #[doc = "\n\nIt is equivalent to the [`" [<u$b>] "`] primitive."]
88        ///
89        /// Also known as a [*natural number*][m0], you can also use the alias
90        #[doc = "[`Natural" $b "`][super::Natural" $b "]."]
91        ///
92        /// [m0]: https://mathworld.wolfram.com/NaturalNumber.html
93        #[derive(Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
94        pub struct [<$name$b>](pub [<$p$b>]);
95
96        impl fmt::Display for [<$name$b>]  {
97            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98                write!(f, "{}", self.0)
99            }
100        }
101        impl fmt::Debug for [<$name$b>]  {
102            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103                write!(f, "{}({})", stringify!([<$abbr$b>]), self.0)
104            }
105        }
106
107        impl [<$name$b>]  {
108            #[doc = "Returns a new `" [<$name$b>] "`."]
109            #[inline]
110            pub const fn new(value: [<$p$b>]) -> Self {
111                Self(value)
112            }
113        }
114
115        /* resizing */
116
117        // uses "try_from"
118        impl_larger_smaller![$name, $b, NonNegativeIntegers,
119            larger: $larger, $larger_b, smaller: $smaller, $smaller_b
120        ];
121
122        /* sign */
123
124        impl Sign for [<$name$b>] {
125            #[inline]
126            fn can_negative(&self) -> bool { false }
127            #[inline]
128            fn can_positive(&self) -> bool { true }
129            #[inline]
130            fn is_negative(&self) -> bool { false }
131            #[inline]
132            fn is_positive(&self) -> bool { self.0.is_positive() }
133        }
134        impl Positive for [<$name$b>] {}
135        impl NonNegative for [<$name$b>] {}
136
137        /* bound */
138
139        impl Bound for [<$name$b>] {
140            #[inline]
141            fn is_lower_bounded(&self) -> bool { true }
142            #[inline]
143            fn is_upper_bounded(&self) -> bool { true }
144            #[inline]
145            fn lower_bound(&self) -> Option<Self> { Some([<$name$b>]::MIN) }
146            #[inline]
147            fn upper_bound(&self) -> Option<Self> { Some([<$name$b>]::MAX) }
148        }
149        impl LowerBounded for [<$name$b>] {
150            #[inline]
151            fn new_min() -> Self { [<$name$b>]::MIN }
152        }
153        impl UpperBounded for [<$name$b>] {
154            #[inline]
155            fn new_max() -> Self { [<$name$b>]::MAX }
156        }
157        impl ConstLowerBounded for [<$name$b>] {
158            const MIN: Self = Self([<$p$b>]::MIN);
159        }
160        impl ConstUpperBounded for [<$name$b>] {
161            const MAX: Self = Self([<$p$b>]::MAX);
162        }
163
164        /* count */
165
166        impl Count for [<$name$b>] {
167            #[inline]
168            fn is_countable(&self) -> bool { true }
169        }
170
171        impl Countable for [<$name$b>] {
172            #[inline]
173            fn next(&self) -> NumeraResult<Self> {
174                Ok(Self(self.0.checked_add(1).ok_or(IntegerErrors::Overflow)?))
175            }
176            #[inline]
177            fn previous(&self) -> NumeraResult<Self> {
178                Ok(Self(self.0.checked_sub(1).ok_or(IntegerErrors::Underflow)?))
179            }
180        }
181
182        /* ident */
183
184        impl Ident for [<$name$b>] {
185            #[inline]
186            fn can_zero(&self) -> bool { true }
187            #[inline]
188            fn can_one(&self) -> bool { true }
189            #[inline]
190            fn can_neg_one(&self) -> bool { false }
191
192            #[inline]
193            fn is_zero(&self) -> bool { self.0 == 0 }
194            #[inline]
195            fn is_one(&self) -> bool { self.0 == 1 }
196            #[inline]
197            fn is_neg_one(&self) -> bool { false }
198        }
199        impl ConstZero for [<$name$b>] { const ZERO: Self = Self(0); }
200        impl Zero for [<$name$b>] {
201            #[inline]
202            fn new_zero() -> Self { Self(0) }
203        }
204        impl ConstOne for [<$name$b>] { const ONE: Self = Self(1); }
205        impl One for [<$name$b>] {
206            #[inline]
207            fn new_one() -> Self { Self(1) }
208        }
209
210        /* number */
211
212        impl Number for [<$name$b>] {
213            type InnerRepr = [<$p$b>];
214            type InnermostRepr = [<$p$b>];
215
216            #[doc = "Returns a new `" [<$name$b>] "` from the inner representation."]
217            ///
218            /// # Errors
219            /// This function can't fail.
220            #[inline]
221            fn from_inner_repr(value: Self::InnerRepr) -> NumeraResult<Self> { Ok(Self(value)) }
222
223            #[doc = "Returns a new `" [<$name$b>] "` from the inner representation."]
224            ///
225            /// # Safety
226            /// This function is safe.
227            #[inline]
228            #[cfg(not(feature = "safe"))]
229            #[cfg_attr(feature = "nightly", doc(cfg(feature = "not(safe)")))]
230            unsafe fn from_inner_repr_unchecked(value: Self::InnerRepr) -> Self { Self(value) }
231
232            #[doc = "Returns a new `" [<$name$b>] "` from the innermost representation."]
233            ///
234            /// # Errors
235            /// This function can't fail.
236            #[inline]
237            fn from_innermost_repr(value: Self::InnermostRepr) -> NumeraResult<Self> {
238                Ok(Self(value))
239            }
240
241            #[doc = "Returns a new `" [<$name$b>] "` from the innermost representation."]
242            ///
243            /// # Safety
244            /// # This function is safe.
245            #[inline]
246            #[cfg(not(feature = "safe"))]
247            #[cfg_attr(feature = "nightly", doc(cfg(feature = "not(safe)")))]
248            unsafe fn from_innermost_repr_unchecked(value: Self::InnermostRepr) -> Self {
249                Self(value)
250            }
251
252            #[inline]
253            fn into_inner_repr(self) -> Self::InnerRepr { self.0 }
254
255            #[inline]
256            fn into_innermost_repr(self) -> Self::InnermostRepr { self.0 }
257        }
258    }};
259}
260
261/* definitions */
262
263define_nonnegative_integer_sized![multi NonNegativeInteger, Nnz, u,
264    "non-negative integer number", ", from the set $\\Z^*$ ($\\N _0$)",
265    // "",
266    "", MIN, MAX,
267    ("An", 8, larger: true, 16, smaller: false, 8),
268    ("A", 16, larger: true, 32, smaller: true, 8),
269    ("A", 32, larger: true, 64, smaller: true, 16),
270    ("A", 64, larger: true, 128, smaller: true, 32),
271    ("A", 128, larger: false, 128, smaller: true, 64)
272];