numera/number/integer/npz/
sized.rs

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