devela/num/int/wrapper/
impl_base.rs
1use crate::{iif, paste, Int};
14
15macro_rules! impl_base {
23 () => {
24 impl_base![signed
25 i8 :"_int_i8" |"",
26 i16 :"_int_i16" |"-1",
27 i32 :"_int_i32" |"-2",
28 i64 :"_int_i64" |"-3",
29 i128 :"_int_i128" |"-4",
30 isize :"_int_isize" |"-5"
31 ];
32 impl_base![unsigned
33 u8 :"_int_u8" |"-6",
34 u16 :"_int_u16" |"-7",
35 u32 :"_int_u32" |"-8",
36 u64 :"_int_u64" |"-9",
37 u128 :"_int_u128" |"-10",
38 usize :"_int_usize" |"-11"
39 ];
40 };
41 (signed $( $t:ty : $cap:literal | $d:literal ),+) => {
42 $( impl_base![@signed $t:$cap | $d]; )+
43 };
44 (unsigned $( $t:ty : $cap:literal | $d:literal ),+) => {
45 $( impl_base![@unsigned $t:$cap | $d]; )+
46 };
47 (
48 @signed $t:ty : $cap:literal | $d:literal) => { paste! {
50 #[doc = crate::doc_availability!(feature = $cap)]
51 #[doc = "# Integer base related methods for `" $t "`\n\n"]
53 #[doc = "- [digits](#method.digits" $d ")"]
54 #[doc = "- [digits_sign](#method.digits_sign" $d ")"]
55 #[doc = "- [digits_base](#method.digits_base" $d ")"]
56 #[doc = "- [digits_base_sign](#method.digits_base_sign" $d ")"]
57 #[doc = "- [digital_root](#method.digital_root" $d ")"]
58 #[doc = "- [digital_root_base](#method.digital_root_base" $d ")"]
59 #[cfg(feature = $cap )]
61 impl Int<$t> {
62 #[doc = "assert_eq![Int(1), Int(0_" $t ").digits()];"]
67 #[doc = "assert_eq![Int(1), Int(-1_" $t ").digits()];"]
68 #[doc = "assert_eq![Int(3), Int(127_" $t ").digits()];"]
69 #[doc = "assert_eq![Int(3), Int(-128_" $t ").digits()];"]
70 #[must_use]
72 pub const fn digits(self) -> Int<$t> {
73 let a = self.0; let n = iif![a == $t::MIN; $t::MAX; a.abs()];
74 iif![let Some(c) = n.checked_ilog10(); Int(c as $t + 1); Int(1)]
75 }
76
77 #[doc = "assert_eq![Int(1), Int(0_" $t ").digits_sign()];"]
82 #[doc = "assert_eq![Int(2), Int(-1_" $t ").digits_sign()];"]
83 #[doc = "assert_eq![Int(3), Int(127_" $t ").digits_sign()];"]
84 #[doc = "assert_eq![Int(4), Int(-128_" $t ").digits_sign()];"]
85 #[must_use]
87 pub const fn digits_sign(self) -> Int<$t> {
88 let a = self.0; let mut res = (a < 0) as $t;
89 let n = iif![a == $t::MIN; $t::MAX; a.abs()];
90 res += iif![let Some(c) = n.checked_ilog10(); c as $t + 1; 1];
91 Int(res)
92 }
93
94 #[doc = "assert_eq![Int(2), Int(3_" $t ").digits_base(2)];"]
101 #[doc = "assert_eq![Int(2), Int(127_" $t ").digits_base(16)];"]
102 #[doc = "assert_eq![Int(2), Int(-128_" $t ").digits_base(16)];"]
103 #[doc = "assert_eq![Int(2), Int(-128_" $t ").digits_base(-16)];"]
104 #[doc = "assert_eq![Int(0), Int(100_" $t ").digits_base(0)];"]
105 #[doc = "assert_eq![Int(1), Int(0_" $t ").digits_base(100)];"]
106 #[must_use]
108 pub const fn digits_base(self, mut base: $t) -> Int<$t> {
109 let mut a = self.0;
110 iif![base == 0; return Int(0)];
111 base = base.abs();
112 a = iif![a == $t::MIN; $t::MAX; a.abs()];
113 iif![let Some(c) = a.checked_ilog(base); Int(c as $t + 1); Int(1)]
114 }
115
116 #[doc = "assert_eq![Int(2), Int(3_" $t ").digits_base_sign(2)];"]
124 #[doc = "assert_eq![Int(2), Int(127_" $t ").digits_base_sign(16)];"]
125 #[doc = "assert_eq![Int(3), Int(-128_" $t ").digits_base_sign(16)];"]
126 #[doc = "assert_eq![Int(3), Int(-128_" $t ").digits_base_sign(-16)];"]
127 #[doc = "assert_eq![Int(0), Int(100_" $t ").digits_base_sign(0)];"]
128 #[doc = "assert_eq![Int(1), Int(0_" $t ").digits_base_sign(100)];"]
129 #[must_use]
131 pub const fn digits_base_sign(self, mut base: $t) -> Int<$t> {
132 let mut a = self.0;
133 iif![base == 0; return Int(0)];
134 base = base.abs();
135 let mut res = (a < 0) as $t;
136 a = iif![a == $t::MIN; $t::MAX; a.abs()];
137 res += iif![let Some(c) = a.checked_ilog(base); c as $t + 1; 1];
138 Int(res)
139 }
140
141 #[doc = "assert_eq![Int(1), Int(127_" $t ").digital_root()];"]
148 #[doc = "assert_eq![Int(1), Int(-127_" $t ").digital_root()];"]
149 #[doc = "assert_eq![Int(9), Int(126_" $t ").digital_root()];"]
150 #[must_use]
152 pub const fn digital_root(self) -> Int<$t> {
153 let mut n = self.0.abs();
154 let mut sum = 0;
155 while n > 0 {
156 sum += n % 10;
157 n /= 10;
158 iif![n == 0 && sum >= 10; { n = sum; sum = 0; }];
159 }
160 Int(sum)
161 }
162
163 #[doc = "assert_eq![Int(1), Int(127_" $t ").digital_root_base(10)];"]
168 #[doc = "assert_eq![Int(1), Int(127_" $t ").digital_root_base(-10)];"]
169 #[doc = "assert_eq![Int(1), Int(-127_" $t ").digital_root_base(-10)];"]
170 #[doc = "assert_eq![Int(9), Int(-126_" $t ").digital_root_base(10)];"]
171 #[doc = "assert_eq![Int(3), Int(-33_" $t ").digital_root_base(16)];"]
172 #[must_use]
174 pub const fn digital_root_base(self, base: $t) -> Int<$t> {
175 let (mut n, base) = (self.0.abs(), base.abs());
176 let mut sum = 0;
177 while n > 0 {
178 sum += n % base;
179 n /= base;
180 iif![n == 0 && sum >= base; { n = sum; sum = 0; }];
181 }
182 Int(sum)
183 }
184 }
185 }};
186 (
187 @unsigned $t:ty : $cap:literal | $d:literal) => { paste! {
189 #[doc = crate::doc_availability!(feature = $cap)]
190 #[doc = "# Integer base related methods for `" $t "`\n\n"]
192 #[doc = "- [digits](#method.digits" $d ")"]
193 #[doc = "- [digits_sign](#method.digits_sign" $d ")"]
194 #[doc = "- [digits_base](#method.digits_base" $d ")"]
195 #[doc = "- [digits_base_sign](#method.digits_base_sign" $d ")"]
196 #[doc = "- [digital_root](#method.digital_root" $d ")"]
197 #[doc = "- [digital_root_base](#method.digital_root_base" $d ")"]
198 #[cfg(feature = $cap )]
200 impl Int<$t> {
201 #[doc = "assert_eq![Int(1), Int(0_" $t ").digits()];"]
208 #[doc = "assert_eq![Int(3), Int(127_" $t ").digits()];"]
209 #[must_use]
211 pub const fn digits(self) -> Int<$t> {
212 iif![let Some(c) = self.0.checked_ilog10(); Int(c as $t + 1); Int(1)]
213 }
214
215 #[must_use]
217 pub const fn digits_sign(self) -> Int<$t> { self.digits() }
218
219 #[doc = "assert_eq![Int(2), Int(3_" $t ").digits_base(2)];"]
226 #[doc = "assert_eq![Int(2), Int(127_" $t ").digits_base(16)];"]
227 #[doc = "assert_eq![Int(0), Int(100_" $t ").digits_base(0)];"]
228 #[doc = "assert_eq![Int(1), Int(0_" $t ").digits_base(100)];"]
229 #[must_use]
231 pub const fn digits_base(self, base: $t) -> Int<$t> {
232 let a = self.0; iif![base == 0; return Int(0)];
233 iif![let Some(c) = a.checked_ilog(base); Int(c as $t + 1); Int(1)]
234 }
235
236 #[must_use]
238 pub const fn digits_base_sign(self, base: $t) -> Int<$t> { self.digits_base(base) }
239
240 #[doc = "assert_eq![Int(1), Int(127_" $t ").digital_root()];"]
247 #[doc = "assert_eq![Int(9), Int(126_" $t ").digital_root()];"]
248 #[must_use]
250 pub const fn digital_root(self) -> Int<$t> {
251 let [mut a, mut sum] = [self.0, 0];
252 while a > 0 {
253 sum += a % 10;
254 a /= 10;
255 iif![a == 0 && sum >= 10; { a = sum; sum = 0; }];
256 }
257 Int(sum)
258 }
259
260 #[doc = "assert_eq![Int(1), Int(127_" $t ").digital_root_base(10)];"]
265 #[doc = "assert_eq![Int(3), Int(33_" $t ").digital_root_base(16)];"]
266 #[must_use]
268 pub const fn digital_root_base(self, base: $t) -> Int<$t> {
269 let [mut a, mut sum] = [self.0, 0];
270 while a > 0 {
271 sum += a % base;
272 a /= base;
273 iif![a == 0 && sum >= base; { a = sum; sum = 0; }];
274 }
275 Int(sum)
276 }
277 }
278 }};
279}
280impl_base!();