reweb3_num/bint/
mod.rs

1macro_rules! ilog {
2    ($method: ident $(, $base: ident : $ty: ty)?) => {
3        #[doc = doc::$method!(I)]
4        #[must_use = doc::must_use_op!()]
5        #[inline]
6        pub const fn $method(self, $($base : $ty),*) -> ExpType {
7            $(
8                if $base.le(&<$ty>::ONE) {
9                    panic!(errors::err_msg!(errors::invalid_log_base!()))
10                }
11            ), *
12            if self.is_negative() {
13                panic!(errors::err_msg!(errors::non_positive_log_message!()))
14            } else {
15                self.bits.$method($($base.bits)?)
16            }
17        }
18    }
19}
20
21#[cfg(debug_assertions)]
22use crate::errors::option_expect;
23
24use crate::digit;
25use crate::ExpType;
26use crate::{doc, errors};
27
28use core::default::Default;
29
30use core::iter::{Iterator, Product, Sum};
31
32macro_rules! mod_impl {
33    ($BUint: ident, $BInt: ident, $Digit: ident) => {
34        /// Big signed integer type, of fixed size which must be known at compile time. Stored as a
35        #[doc = concat!(" [`", stringify!($BUint), "`].")]
36        ///
37        /// Digits of the underlying
38        #[doc = concat!("[`", stringify!($BUint), "`](crate::", stringify!($BUint), ")")]
39        /// are stored in little endian (least significant digit first). This integer type aims to exactly replicate the behaviours of Rust's built-in signed integer types: [`i8`], [`i16`], [`i32`], [`i64`], [`i128`] and [`isize`]. The const generic parameter `N` is the number of digits that are stored in the underlying
40        #[doc = concat!("[`", stringify!($BUint), "`].")]
41        ///
42        #[doc = doc::arithmetic_doc!($BInt)]
43
44        #[derive(Clone, Copy, Hash, PartialEq, Eq)]
45        #[repr(transparent)]
46        pub struct $BInt<const N: usize> {
47            pub(crate) bits: $BUint<N>,
48        }
49
50        impl<const N: usize> $BInt<N> {
51            #[doc = doc::count_ones!(I 256)]
52            #[must_use = doc::must_use_op!()]
53            #[inline]
54            pub const fn count_ones(self) -> ExpType {
55                self.bits.count_ones()
56            }
57
58            #[doc = doc::count_zeros!(I 256)]
59            #[must_use = doc::must_use_op!()]
60            #[inline]
61            pub const fn count_zeros(self) -> ExpType {
62                self.bits.count_zeros()
63            }
64
65            #[doc = doc::leading_zeros!(I 256)]
66            #[must_use = doc::must_use_op!()]
67            #[inline]
68            pub const fn leading_zeros(self) -> ExpType {
69                self.bits.leading_zeros()
70            }
71
72            #[doc = doc::trailing_zeros!(I 256)]
73            #[must_use = doc::must_use_op!()]
74            #[inline]
75            pub const fn trailing_zeros(self) -> ExpType {
76                self.bits.trailing_zeros()
77            }
78
79            #[doc = doc::leading_ones!(I 256, NEG_ONE)]
80            #[must_use = doc::must_use_op!()]
81            #[inline]
82            pub const fn leading_ones(self) -> ExpType {
83                self.bits.leading_ones()
84            }
85
86            #[doc = doc::trailing_ones!(I 256)]
87            #[must_use = doc::must_use_op!()]
88            #[inline]
89            pub const fn trailing_ones(self) -> ExpType {
90                self.bits.trailing_ones()
91            }
92
93            #[doc = doc::rotate_left!(I 256, "i")]
94            #[must_use = doc::must_use_op!()]
95            #[inline]
96            pub const fn rotate_left(self, n: ExpType) -> Self {
97                Self::from_bits(self.bits.rotate_left(n))
98            }
99
100            #[doc = doc::rotate_right!(I 256, "i")]
101            #[must_use = doc::must_use_op!()]
102            #[inline]
103            pub const fn rotate_right(self, n: ExpType) -> Self {
104                Self::from_bits(self.bits.rotate_right(n))
105            }
106
107            #[doc = doc::swap_bytes!(I 256, "i")]
108            #[must_use = doc::must_use_op!()]
109            #[inline]
110            pub const fn swap_bytes(self) -> Self {
111                Self::from_bits(self.bits.swap_bytes())
112            }
113
114            #[doc = doc::reverse_bits!(I 256, "i")]
115            #[must_use = doc::must_use_op!()]
116            #[inline]
117            pub const fn reverse_bits(self) -> Self {
118                Self::from_bits(self.bits.reverse_bits())
119            }
120
121            #[doc = doc::unsigned_abs!(I)]
122            #[must_use = doc::must_use_op!()]
123            #[inline]
124            pub const fn unsigned_abs(self) -> $BUint<N> {
125                if self.is_negative() {
126                    self.wrapping_neg().bits
127                } else {
128                    self.bits
129                }
130            }
131
132            #[doc = doc::pow!(I 256)]
133            #[must_use = doc::must_use_op!()]
134            #[inline]
135            pub const fn pow(self, exp: ExpType) -> Self {
136                #[cfg(debug_assertions)]
137                return option_expect!(self.checked_pow(exp), errors::err_msg!("attempt to calculate power with overflow"));
138
139                #[cfg(not(debug_assertions))]
140                self.wrapping_pow(exp)
141            }
142
143            #[doc = doc::div_euclid!(I)]
144            #[must_use = doc::must_use_op!()]
145            #[inline]
146            pub const fn div_euclid(self, rhs: Self) -> Self {
147                assert!(self.ne(&Self::MIN) || rhs.ne(&Self::NEG_ONE), errors::err_msg!("attempt to divide with overflow"));
148                self.wrapping_div_euclid(rhs)
149            }
150
151            #[doc = doc::rem_euclid!(I)]
152            #[must_use = doc::must_use_op!()]
153            #[inline]
154            pub const fn rem_euclid(self, rhs: Self) -> Self {
155                assert!(self.ne(&Self::MIN) || rhs.ne(&Self::NEG_ONE), errors::err_msg!("attempt to calculate remainder with overflow"));
156                self.wrapping_rem_euclid(rhs)
157            }
158
159            #[doc = doc::abs!(I)]
160            #[must_use = doc::must_use_op!()]
161            #[inline]
162            pub const fn abs(self) -> Self {
163                #[cfg(debug_assertions)]
164                return option_expect!(self.checked_abs(), errors::err_msg!("attempt to negate with overflow"));
165
166                #[cfg(not(debug_assertions))]
167                match self.checked_abs() {
168                    Some(int) => int,
169                    None => Self::MIN,
170                }
171            }
172
173            #[doc = doc::signum!(I)]
174            #[must_use = doc::must_use_op!()]
175            #[inline]
176            pub const fn signum(self) -> Self {
177                if self.is_negative() {
178                    Self::NEG_ONE
179                } else if self.is_zero() {
180                    Self::ZERO
181                } else {
182                    Self::ONE
183                }
184            }
185
186            #[doc = doc::is_positive!(I)]
187            #[must_use = doc::must_use_op!()]
188            #[inline]
189            pub const fn is_positive(self) -> bool {
190                let signed_digit = self.signed_digit();
191                signed_digit.is_positive() || (signed_digit == 0 && !self.bits.is_zero())
192            }
193
194            #[doc = doc::is_negative!(I)]
195            #[must_use = doc::must_use_op!()]
196            #[inline]
197            pub const fn is_negative(self) -> bool {
198                self.signed_digit().is_negative()
199            }
200
201            #[doc = doc::doc_comment! {
202                I 256,
203                "Returns `true` if and only if `self == 2^k` for some integer `k`.",
204
205                "let n = " stringify!(I256) "::from(1i16 << 12);\n"
206                "assert!(n.is_power_of_two());\n"
207                "let m = " stringify!(I256) "::from(90i8);\n"
208                "assert!(!m.is_power_of_two());\n"
209                "assert!(!((-n).is_power_of_two()));"
210            }]
211            #[must_use]
212            #[inline]
213            pub const fn is_power_of_two(self) -> bool {
214                !self.is_negative() &&self.bits.is_power_of_two()
215            }
216
217            ilog!(ilog, base: Self);
218            ilog!(ilog2);
219            ilog!(ilog10);
220
221            #[doc = doc::abs_diff!(I)]
222            #[must_use = doc::must_use_op!()]
223            #[inline]
224            pub const fn abs_diff(self, other: Self) -> $BUint<N> {
225                if self.lt(&other) {
226                    other.wrapping_sub(self).to_bits()
227                } else {
228                    self.wrapping_sub(other).to_bits()
229                }
230            }
231
232            #[doc = doc::next_multiple_of!(I)]
233            #[must_use = doc::must_use_op!()]
234            #[inline]
235            pub const fn next_multiple_of(self, rhs: Self) -> Self {
236                let rem = self.wrapping_rem_euclid(rhs);
237                if rem.is_zero() {
238                    return self;
239                }
240                if rem.is_negative() == rhs.is_negative() {
241                    self.add(rhs.sub(rem))
242                } else {
243                    self.sub(rem)
244                }
245            }
246
247            #[doc = doc::div_floor!(I)]
248            #[must_use = doc::must_use_op!()]
249            #[inline]
250            pub const fn div_floor(self, rhs: Self) -> Self {
251                if rhs.is_zero() {
252                    errors::div_zero!();
253                }
254                let (div, rem) = self.div_rem_unchecked(rhs);
255                if rem.is_zero() || self.is_negative() == rhs.is_negative() {
256                    div
257                } else {
258                    div.sub(Self::ONE)
259                }
260            }
261
262            #[doc = doc::div_ceil!(I)]
263            #[must_use = doc::must_use_op!()]
264            #[inline]
265            pub const fn div_ceil(self, rhs: Self) -> Self {
266                if rhs.is_zero() {
267                    errors::div_zero!();
268                }
269                let (div, rem) = self.div_rem_unchecked(rhs);
270                if rem.is_zero() || self.is_negative() != rhs.is_negative() {
271                    div
272                } else {
273                    div.add(Self::ONE)
274                }
275            }
276        }
277
278        impl<const N: usize> $BInt<N> {
279            #[doc = doc::bits!(I 256)]
280            #[must_use]
281            #[inline]
282            pub const fn bits(&self) -> ExpType {
283                self.bits.bits()
284            }
285
286            #[doc = doc::bit!(I 256)]
287            #[must_use]
288            #[inline]
289            pub const fn bit(&self, b: ExpType) -> bool {
290                self.bits.bit(b)
291            }
292
293            #[inline(always)]
294            pub(crate) const fn signed_digit(&self) -> digit::$Digit::SignedDigit {
295                self.bits.digits[N - 1] as _
296            }
297
298            #[doc = doc::is_zero!(I 256)]
299            #[must_use]
300            #[inline]
301            pub const fn is_zero(&self) -> bool {
302                self.bits.is_zero()
303            }
304
305            #[doc = doc::is_one!(I 256)]
306            #[must_use]
307            #[inline]
308            pub const fn is_one(&self) -> bool {
309                self.bits.is_one()
310            }
311
312            /// Creates a signed integer with `bits` as its underlying representation in two's complement.
313            ///
314            /// This method is faster for casting from a
315            #[doc = concat!("[`", stringify!($BUint), "`]")]
316            /// to a
317            #[doc = concat!("[`", stringify!($BInt), "`]")]
318            /// of the same size than using the `As` trait.
319            #[must_use]
320            #[inline(always)]
321            pub const fn from_bits(bits: $BUint<N>) -> Self {
322                Self { bits }
323            }
324
325            /// This simply returns the underlying representation of the integer in two's complement, as an unsigned integer.
326            ///
327            /// This method is faster for casting from a
328            #[doc = concat!("[`", stringify!($BInt), "`]")]
329            /// to a
330            #[doc = concat!("[`", stringify!($BUint), "`]")]
331            /// of the same size than using the `As` trait.
332            #[must_use]
333            #[inline(always)]
334            pub const fn to_bits(self) -> $BUint<N> {
335                self.bits
336            }
337        }
338
339        impl<const N: usize> Default for $BInt<N> {
340            #[doc = doc::default!()]
341            #[inline]
342            fn default() -> Self {
343                Self::ZERO
344            }
345        }
346
347        impl<const N: usize> Product<Self> for $BInt<N> {
348            #[inline]
349            fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
350                iter.fold(Self::ONE, |a, b| a * b)
351            }
352        }
353
354        impl<'a, const N: usize> Product<&'a Self> for $BInt<N> {
355            #[inline]
356            fn product<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
357                iter.fold(Self::ONE, |a, b| a * b)
358            }
359        }
360
361        impl<const N: usize> Sum<Self> for $BInt<N> {
362            #[inline]
363            fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
364                iter.fold(Self::ZERO, |a, b| a + b)
365            }
366        }
367
368        impl<'a, const N: usize> Sum<&'a Self> for $BInt<N> {
369            #[inline]
370            fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
371                iter.fold(Self::ZERO, |a, b| a + b)
372            }
373        }
374
375        #[cfg(any(test))]
376        impl<const N: usize> quickcheck::Arbitrary for $BInt<N> {
377            #[inline]
378            fn arbitrary(g: &mut quickcheck::Gen) -> Self {
379                Self::from_bits(<$BUint::<N> as quickcheck::Arbitrary>::arbitrary(g))
380            }
381        }
382    };
383}
384
385crate::macro_impl!(mod_impl);
386
387pub mod cast;
388mod checked;
389mod cmp;
390mod const_trait_fillers;
391mod consts;
392mod convert;
393mod endian;
394mod fmt;
395#[cfg(feature = "numtraits")]
396mod numtraits;
397mod ops;
398mod overflowing;
399mod radix;
400mod saturating;
401mod unchecked;
402mod wrapping;