devela/num/int/wrapper/
impl_base.rsuse crate::{iif, paste, Int};
macro_rules! impl_base {
() => {
impl_base![signed
i8 :"_int_i8" |"",
i16 :"_int_i16" |"-1",
i32 :"_int_i32" |"-2",
i64 :"_int_i64" |"-3",
i128 :"_int_i128" |"-4",
isize :"_int_isize" |"-5"
];
impl_base![unsigned
u8 :"_int_u8" |"-6",
u16 :"_int_u16" |"-7",
u32 :"_int_u32" |"-8",
u64 :"_int_u64" |"-9",
u128 :"_int_u128" |"-10",
usize :"_int_usize" |"-11"
];
};
(signed $( $t:ty : $cap:literal | $d:literal ),+) => {
$( impl_base![@signed $t:$cap | $d]; )+
};
(unsigned $( $t:ty : $cap:literal | $d:literal ),+) => {
$( impl_base![@unsigned $t:$cap | $d]; )+
};
(
@signed $t:ty : $cap:literal | $d:literal) => { paste! {
#[doc = crate::doc_availability!(feature = $cap)]
#[doc = "# Integer base related methods for `" $t "`\n\n"]
#[doc = "- [digits](#method.digits" $d ")"]
#[doc = "- [digits_sign](#method.digits_sign" $d ")"]
#[doc = "- [digits_base](#method.digits_base" $d ")"]
#[doc = "- [digits_base_sign](#method.digits_base_sign" $d ")"]
#[doc = "- [digital_root](#method.digital_root" $d ")"]
#[doc = "- [digital_root_base](#method.digital_root_base" $d ")"]
#[cfg(feature = $cap )]
impl Int<$t> {
#[doc = "assert_eq![Int(1), Int(0_" $t ").digits()];"]
#[doc = "assert_eq![Int(1), Int(-1_" $t ").digits()];"]
#[doc = "assert_eq![Int(3), Int(127_" $t ").digits()];"]
#[doc = "assert_eq![Int(3), Int(-128_" $t ").digits()];"]
#[must_use]
pub const fn digits(self) -> Int<$t> {
let a = self.0; let n = iif![a == $t::MIN; $t::MAX; a.abs()];
iif![let Some(c) = n.checked_ilog10(); Int(c as $t + 1); Int(1)]
}
#[doc = "assert_eq![Int(1), Int(0_" $t ").digits_sign()];"]
#[doc = "assert_eq![Int(2), Int(-1_" $t ").digits_sign()];"]
#[doc = "assert_eq![Int(3), Int(127_" $t ").digits_sign()];"]
#[doc = "assert_eq![Int(4), Int(-128_" $t ").digits_sign()];"]
#[must_use]
pub const fn digits_sign(self) -> Int<$t> {
let a = self.0; let mut res = (a < 0) as $t;
let n = iif![a == $t::MIN; $t::MAX; a.abs()];
res += iif![let Some(c) = n.checked_ilog10(); c as $t + 1; 1];
Int(res)
}
#[doc = "assert_eq![Int(2), Int(3_" $t ").digits_base(2)];"]
#[doc = "assert_eq![Int(2), Int(127_" $t ").digits_base(16)];"]
#[doc = "assert_eq![Int(2), Int(-128_" $t ").digits_base(16)];"]
#[doc = "assert_eq![Int(2), Int(-128_" $t ").digits_base(-16)];"]
#[doc = "assert_eq![Int(0), Int(100_" $t ").digits_base(0)];"]
#[doc = "assert_eq![Int(1), Int(0_" $t ").digits_base(100)];"]
#[must_use]
pub const fn digits_base(self, mut base: $t) -> Int<$t> {
let mut a = self.0;
iif![base == 0; return Int(0)];
base = base.abs();
a = iif![a == $t::MIN; $t::MAX; a.abs()];
iif![let Some(c) = a.checked_ilog(base); Int(c as $t + 1); Int(1)]
}
#[doc = "assert_eq![Int(2), Int(3_" $t ").digits_base_sign(2)];"]
#[doc = "assert_eq![Int(2), Int(127_" $t ").digits_base_sign(16)];"]
#[doc = "assert_eq![Int(3), Int(-128_" $t ").digits_base_sign(16)];"]
#[doc = "assert_eq![Int(3), Int(-128_" $t ").digits_base_sign(-16)];"]
#[doc = "assert_eq![Int(0), Int(100_" $t ").digits_base_sign(0)];"]
#[doc = "assert_eq![Int(1), Int(0_" $t ").digits_base_sign(100)];"]
#[must_use]
pub const fn digits_base_sign(self, mut base: $t) -> Int<$t> {
let mut a = self.0;
iif![base == 0; return Int(0)];
base = base.abs();
let mut res = (a < 0) as $t;
a = iif![a == $t::MIN; $t::MAX; a.abs()];
res += iif![let Some(c) = a.checked_ilog(base); c as $t + 1; 1];
Int(res)
}
#[doc = "assert_eq![Int(1), Int(127_" $t ").digital_root()];"]
#[doc = "assert_eq![Int(1), Int(-127_" $t ").digital_root()];"]
#[doc = "assert_eq![Int(9), Int(126_" $t ").digital_root()];"]
#[must_use]
pub const fn digital_root(self) -> Int<$t> {
let mut n = self.0.abs();
let mut sum = 0;
while n > 0 {
sum += n % 10;
n /= 10;
iif![n == 0 && sum >= 10; { n = sum; sum = 0; }];
}
Int(sum)
}
#[doc = "assert_eq![Int(1), Int(127_" $t ").digital_root_base(10)];"]
#[doc = "assert_eq![Int(1), Int(127_" $t ").digital_root_base(-10)];"]
#[doc = "assert_eq![Int(1), Int(-127_" $t ").digital_root_base(-10)];"]
#[doc = "assert_eq![Int(9), Int(-126_" $t ").digital_root_base(10)];"]
#[doc = "assert_eq![Int(3), Int(-33_" $t ").digital_root_base(16)];"]
#[must_use]
pub const fn digital_root_base(self, base: $t) -> Int<$t> {
let (mut n, base) = (self.0.abs(), base.abs());
let mut sum = 0;
while n > 0 {
sum += n % base;
n /= base;
iif![n == 0 && sum >= base; { n = sum; sum = 0; }];
}
Int(sum)
}
}
}};
(
@unsigned $t:ty : $cap:literal | $d:literal) => { paste! {
#[doc = crate::doc_availability!(feature = $cap)]
#[doc = "# Integer base related methods for `" $t "`\n\n"]
#[doc = "- [digits](#method.digits" $d ")"]
#[doc = "- [digits_sign](#method.digits_sign" $d ")"]
#[doc = "- [digits_base](#method.digits_base" $d ")"]
#[doc = "- [digits_base_sign](#method.digits_base_sign" $d ")"]
#[doc = "- [digital_root](#method.digital_root" $d ")"]
#[doc = "- [digital_root_base](#method.digital_root_base" $d ")"]
#[cfg(feature = $cap )]
impl Int<$t> {
#[doc = "assert_eq![Int(1), Int(0_" $t ").digits()];"]
#[doc = "assert_eq![Int(3), Int(127_" $t ").digits()];"]
#[must_use]
pub const fn digits(self) -> Int<$t> {
iif![let Some(c) = self.0.checked_ilog10(); Int(c as $t + 1); Int(1)]
}
#[must_use]
pub const fn digits_sign(self) -> Int<$t> { self.digits() }
#[doc = "assert_eq![Int(2), Int(3_" $t ").digits_base(2)];"]
#[doc = "assert_eq![Int(2), Int(127_" $t ").digits_base(16)];"]
#[doc = "assert_eq![Int(0), Int(100_" $t ").digits_base(0)];"]
#[doc = "assert_eq![Int(1), Int(0_" $t ").digits_base(100)];"]
#[must_use]
pub const fn digits_base(self, base: $t) -> Int<$t> {
let a = self.0; iif![base == 0; return Int(0)];
iif![let Some(c) = a.checked_ilog(base); Int(c as $t + 1); Int(1)]
}
#[must_use]
pub const fn digits_base_sign(self, base: $t) -> Int<$t> { self.digits_base(base) }
#[doc = "assert_eq![Int(1), Int(127_" $t ").digital_root()];"]
#[doc = "assert_eq![Int(9), Int(126_" $t ").digital_root()];"]
#[must_use]
pub const fn digital_root(self) -> Int<$t> {
let [mut a, mut sum] = [self.0, 0];
while a > 0 {
sum += a % 10;
a /= 10;
iif![a == 0 && sum >= 10; { a = sum; sum = 0; }];
}
Int(sum)
}
#[doc = "assert_eq![Int(1), Int(127_" $t ").digital_root_base(10)];"]
#[doc = "assert_eq![Int(3), Int(33_" $t ").digital_root_base(16)];"]
#[must_use]
pub const fn digital_root_base(self, base: $t) -> Int<$t> {
let [mut a, mut sum] = [self.0, 0];
while a > 0 {
sum += a % base;
a /= base;
iif![a == 0 && sum >= base; { a = sum; sum = 0; }];
}
Int(sum)
}
}
}};
}
impl_base!();