use crate::{Arbi, Digit};
use core::ops::Shr;
macro_rules! impl_from_integral {
($($signed:ty => $unsigned:ty),*) => {
$(
#[allow(unused_comparisons)]
impl From<$signed> for Arbi {
fn from(value: $signed) -> Self {
type UnsignedT = $unsigned;
let mut uvalue: UnsignedT;
let mut x = Arbi::zero();
if value == 0 {
return x;
} else if value < 0 {
uvalue = (0 as UnsignedT).wrapping_sub(value as UnsignedT);
x.neg = true;
} else {
uvalue = value as UnsignedT;
x.neg = false;
}
if UnsignedT::BITS <= Digit::BITS {
x.vec.resize(1, 0);
x.vec[0] = uvalue as Digit;
return x;
}
let mut size = 1;
let mut temp: UnsignedT = uvalue;
loop {
temp = temp.shr(Digit::BITS); if temp == 0 {
break;
}
size += 1;
}
x.vec.resize(size, 0);
let mut i = 0;
while uvalue != 0 {
x.vec[i] = uvalue as Digit;
uvalue = uvalue.shr(Digit::BITS); i += 1;
}
x
}
}
impl From<&$signed> for Arbi {
fn from(value: &$signed) -> Self {
Arbi::from(*value)
}
}
)*
}
}
impl_from_integral!(
i8 => u8,
i16 => u16,
i32 => u32,
i64 => u64,
i128 => u128,
isize => usize,
u8 => u8,
u16 => u16,
u32 => u32,
u64 => u64,
u128 => u128,
usize => usize
);
#[cfg(test)]
mod test_internal_representation_after_from_integral {
use super::*;
use crate::{DDigit, QDigit, SDDigit};
use alloc::string::ToString;
#[test]
fn test_digit_max() {
let digit_max: Arbi = Digit::MAX.into();
assert_eq!(digit_max.vec.len(), 1);
assert_eq!(digit_max.vec[0], Digit::MAX);
assert_eq!(digit_max.neg, false);
}
#[test]
fn test_digit_max_plus_one() {
let digit_max: Arbi = (Digit::MAX as DDigit + 1).into();
assert_eq!(digit_max.vec.len(), 2);
assert_eq!(digit_max.vec[0], 0);
assert_eq!(digit_max.vec[1], 1);
assert_eq!(digit_max.neg, false);
}
#[test]
fn test_minus_digit_max() {
let minus_digit_max: Arbi = (-(Digit::MAX as i128)).into();
assert_eq!(minus_digit_max.vec.len(), 1);
assert_eq!(minus_digit_max.vec[0], Digit::MAX);
assert_eq!(minus_digit_max.neg, true);
}
#[test]
fn test_minus_digit_max_plus_one() {
let minus_digit_max: Arbi = (-(Digit::MAX as SDDigit + 1)).into();
assert_eq!(minus_digit_max.vec.len(), 2);
assert_eq!(minus_digit_max.vec[0], 0);
assert_eq!(minus_digit_max.vec[1], 1);
assert_eq!(minus_digit_max.neg, true);
}
#[test]
fn test_ddigit_max() {
let ddigit_max = Arbi::from(DDigit::MAX);
assert_eq!(ddigit_max, DDigit::MAX);
}
#[test]
fn test_construct_from_integrals() {
for i in 1 as Digit..u16::MAX as Digit {
let a = Arbi::from(i);
assert_eq!(a.size(), 1);
assert_eq!(a.vec[0], i);
assert_eq!(a.to_string(), i.to_string());
assert_eq!(a, i);
}
for i in 0 as Digit..u16::MAX as Digit {
let a = Arbi::from(DDigit::MAX - i as DDigit);
assert_eq!(a.size(), 2);
assert_eq!(a.vec[0], Digit::MAX - i);
assert_eq!(a.vec[1], Digit::MAX);
assert_eq!(a.to_string(), (DDigit::MAX - i as DDigit).to_string());
assert_eq!(a, DDigit::MAX - i as DDigit);
}
for i in 0 as Digit..u16::MAX as Digit {
let a = Arbi::from(QDigit::MAX - i as QDigit);
assert_eq!(a.size(), 4);
assert_eq!(a.vec[0], Digit::MAX - i);
assert_eq!(a.vec[1], Digit::MAX);
assert_eq!(a.vec[2], Digit::MAX);
assert_eq!(a.vec[3], Digit::MAX);
assert_eq!(a.to_string(), (QDigit::MAX - i as QDigit).to_string());
assert_eq!(a, QDigit::MAX - i as QDigit);
}
for i in i16::MIN..0 {
let a = Arbi::from(i);
assert_eq!(a.is_negative(), true);
assert_eq!(a.size(), 1);
assert_eq!(a.vec[0], i.unsigned_abs() as Digit);
assert_eq!(a.to_string(), i.to_string());
assert_eq!(a, i);
}
for i in 1..i16::MAX {
let a = Arbi::from(i);
assert_eq!(a.is_negative(), false);
assert_eq!(a.size(), 1);
assert_eq!(a.vec[0], i as Digit);
assert_eq!(a.to_string(), i.to_string());
assert_eq!(a, i);
}
for i in 0..u16::MAX {
let a = Arbi::from(SDDigit::MAX - i as SDDigit);
assert_eq!(a.is_negative(), false);
assert_eq!(a.size(), 2);
assert_eq!(a.vec[0], Digit::MAX - i as Digit);
assert_eq!(
a.vec[1],
((1 as Digit) << (Digit::BITS - 1)) - 1 as Digit
);
assert_eq!(
a.to_string(),
(SDDigit::MAX - i as SDDigit).to_string()
);
assert_eq!(a, SDDigit::MAX - i as SDDigit);
}
for i in 0..u16::MAX {
let a = Arbi::from(SDDigit::MIN + i as SDDigit);
assert_eq!(a.is_negative(), true);
assert_eq!(a.size(), 2);
if i == 0 {
assert_eq!(a.vec[0], i as Digit);
assert_eq!(a.vec[1], (1 as Digit) << (Digit::BITS - 1));
} else {
assert_eq!(a.vec[0], Digit::MAX - i as Digit + 1);
assert_eq!(
a.vec[1],
((1 as Digit) << (Digit::BITS - 1)) - 1 as Digit
);
}
assert_eq!(
a.to_string(),
(SDDigit::MIN + i as SDDigit).to_string()
);
assert_eq!(a, SDDigit::MIN + i as SDDigit);
}
}
}