extern crate self as big_int;
use std::{
cmp::Ordering,
fmt::Display,
ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Shl, ShlAssign, Shr, ShrAssign, Sub,
SubAssign,
},
str::FromStr,
};
use error::{BigIntError, ParseError};
use get_back::GetBack;
use self::Sign::*;
pub use big_int_proc::*;
pub mod prelude {
pub use crate::denormal::*;
pub use crate::loose::*;
pub use crate::tight::*;
pub use crate::Sign::*;
pub use crate::*;
}
mod tests;
pub(crate) mod test_utils;
pub mod base64;
pub mod denormal;
pub mod error;
pub mod get_back;
pub mod loose;
pub mod tight;
pub const STANDARD_ALPHABET: &str =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
pub type Digit = u64;
pub(crate) type DoubleDigit = u128;
#[macro_export(local_inner_macros)]
macro_rules! mask {
($n:expr) => {
(((1 << (($n) - 1)) - 1) << 1) + 1
};
}
pub trait BigInt<const BASE: usize>
where
Self: GetBack<Item = Digit>
+ Clone
+ Default
+ std::fmt::Debug
+ Display
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Neg<Output = Self>
+ Add<Output = Self>
+ AddAssign
+ Sub<Output = Self>
+ SubAssign
+ Div<Output = Self>
+ DivAssign
+ Mul<Output = Self>
+ MulAssign
+ Shl<Output = Self>
+ ShlAssign
+ Shr<Output = Self>
+ ShrAssign
+ FromStr<Err = BigIntError>
+ FromIterator<Digit>
+ IntoIterator<Item = Digit, IntoIter = BigIntIntoIter<BASE, Self>>
+ From<Vec<Digit>>
+ From<u8>
+ From<u16>
+ From<u32>
+ From<u64>
+ From<u128>
+ From<usize>
+ From<i8>
+ From<i16>
+ From<i32>
+ From<i64>
+ From<i128>
+ From<isize>
+ Into<u8>
+ Into<u16>
+ Into<u32>
+ Into<u64>
+ Into<u128>
+ Into<usize>
+ Into<i8>
+ Into<i16>
+ Into<i32>
+ Into<i64>
+ Into<i128>
+ Into<isize>,
{
type Builder: BigIntBuilder<{ BASE }> + Into<Self::Denormal> + Into<Self>;
type Denormal: BigInt<BASE> + From<Self> + UnsafeInto<Self> + Unwrap<Self>;
const BITS_PER_DIGIT: usize = bits_per_digit(BASE);
fn get_back_inner(&self, index: usize) -> Option<Digit> {
self.len()
.checked_sub(index)
.and_then(|index| self.get_digit(index))
}
fn default_inner() -> Self {
Self::zero()
}
fn fmt_inner(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
self.display(STANDARD_ALPHABET)
.map_err(|_| std::fmt::Error)?
)
}
fn partial_cmp_inner<RHS: BigInt<{ BASE }>>(&self, other: &RHS) -> Option<Ordering> {
Some(self.cmp_inner(other))
}
fn cmp_inner<RHS: BigInt<{ BASE }>>(&self, other: &RHS) -> Ordering {
if self.is_zero() && other.is_zero() {
Ordering::Equal
} else {
match (self.sign(), other.sign()) {
(Positive, Negative) => Ordering::Greater,
(Negative, Positive) => Ordering::Less,
(Positive, Positive) => self.cmp_magnitude(other),
(Negative, Negative) => other.cmp_magnitude(self),
}
}
}
fn eq_inner<RHS: BigInt<{ BASE }>>(&self, other: &RHS) -> bool {
matches!(self.cmp_inner(other), Ordering::Equal)
}
fn neg_inner(self) -> Self::Denormal {
let sign = self.sign();
self.with_sign(-sign).into()
}
fn add_inner<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(self, rhs: RHS) -> OUT::Denormal {
if self.sign() != rhs.sign() {
self.sub_inner::<_, OUT>(rhs.neg())
} else {
let sign = self.sign();
let mut carry = 0;
let mut result = OUT::Builder::new();
for i in 1.. {
match (self.get_back(i), rhs.get_back(i), carry) {
(None, None, 0) => break,
(left_digit, right_digit, carry_in) => {
let left_digit = left_digit.unwrap_or_default() as DoubleDigit;
let right_digit = right_digit.unwrap_or_default() as DoubleDigit;
let mut sum = left_digit + right_digit + carry_in;
if sum >= BASE as DoubleDigit {
sum -= BASE as DoubleDigit;
carry = 1;
} else {
carry = 0;
}
result.push_front(sum as Digit);
}
}
}
result.with_sign(sign).into()
}
}
unsafe fn add_assign_inner<RHS: BigInt<{ BASE }>>(&mut self, rhs: RHS) {
if self.sign() != rhs.sign() {
self.sub_assign_inner(rhs.neg_inner());
} else {
let self_len = self.len();
let mut carry = 0;
for i in 1.. {
match (self.get_back(i), rhs.get_back(i), carry) {
(None, None, 0) => break,
(left_digit, right_digit, carry_in) => {
let left_digit = left_digit.unwrap_or_default() as DoubleDigit;
let right_digit = right_digit.unwrap_or_default() as DoubleDigit;
let mut sum = left_digit + right_digit + carry_in;
if sum >= BASE as DoubleDigit {
sum -= BASE as DoubleDigit;
carry = 1;
} else {
carry = 0;
}
if i <= self_len {
self.set_digit(self_len - i, sum as Digit);
} else {
self.push_front(sum as Digit);
}
}
}
}
}
}
fn sub_inner<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(
mut self,
rhs: RHS,
) -> OUT::Denormal {
if self.sign() != rhs.sign() {
self.add_inner::<_, OUT>(rhs.neg_inner())
} else if rhs.cmp_magnitude(&self).is_gt() {
unsafe { rhs.sub_inner::<_, OUT>(self).unsafe_into() }.neg_inner()
} else {
let sign = self.sign();
let mut result = OUT::Builder::new();
let self_len = self.len();
for i in 1.. {
match (self.get_back(i), rhs.get_back(i)) {
(None, None) => break,
(left_digit, right_digit) => {
let mut left_digit = left_digit.unwrap_or_default() as DoubleDigit;
let right_digit = right_digit.unwrap_or_default() as DoubleDigit;
if left_digit < right_digit {
for j in i + 1.. {
match self.get_back(j) {
None => unreachable!("big int subtraction with overflow"),
Some(0) => {
self.set_digit(self_len - j, (BASE - 1) as Digit);
}
Some(digit) => {
self.set_digit(self_len - j, digit - 1);
break;
}
}
}
left_digit += BASE as DoubleDigit;
}
result.push_front((left_digit - right_digit) as Digit);
}
}
}
result.with_sign(sign).into()
}
}
unsafe fn sub_assign_inner<RHS: BigInt<{ BASE }>>(&mut self, rhs: RHS) {
if self.sign() != rhs.sign() {
self.add_assign_inner(rhs.neg_inner());
} else if rhs.cmp_magnitude(self).is_gt() {
*self = rhs
.sub_inner::<_, Self>(self.clone())
.unsafe_into()
.neg_inner()
.unsafe_into();
} else {
let self_len = self.len();
for i in 1.. {
match (self.get_back(i), rhs.get_back(i)) {
(None, None) => break,
(left_digit, right_digit) => {
let mut left_digit = left_digit.unwrap_or_default() as DoubleDigit;
let right_digit = right_digit.unwrap_or_default() as DoubleDigit;
if left_digit < right_digit {
for j in i + 1.. {
match self.get_back(j) {
None => unreachable!("big int subtraction with overflow"),
Some(0) => {
self.set_digit(self_len - j, (BASE - 1) as Digit);
}
Some(digit) => {
self.set_digit(self_len - j, digit - 1);
break;
}
}
}
left_digit += BASE as DoubleDigit;
}
let difference = (left_digit - right_digit) as Digit;
if i <= self_len {
self.set_digit(self_len - i, difference);
} else {
self.push_front(difference);
}
}
}
}
}
}
fn mul_inner<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(
mut self,
mut rhs: RHS,
) -> OUT::Denormal {
let sign = self.sign() * rhs.sign();
self.set_sign(Positive);
rhs.set_sign(Positive);
let mut shift = 0;
if !self.is_zero() {
while let Some(0) = self.get_back(1) {
unsafe {
self.shr_assign_inner(1);
}
shift += 1;
}
}
if !rhs.is_zero() {
while let Some(0) = rhs.get_back(1) {
unsafe {
rhs.shr_assign_inner(1);
}
shift += 1;
}
}
let mut result = OUT::zero();
let mut addends = rhs.clone().addends().memo();
for digit in self.into_iter().rev() {
for index in 0..Self::BITS_PER_DIGIT {
if digit & (1 << index) != 0 {
unsafe {
result.add_assign_inner(addends.get(index).unwrap().clone());
}
}
unsafe {
addends.get_mut(index).unwrap().shl_assign_inner(1);
}
}
}
OUT::from(result.with_sign(sign)).shl_inner(shift)
}
unsafe fn mul_assign_inner<RHS: BigInt<{ BASE }>>(&mut self, rhs: RHS) {
*self = self.clone().mul_inner::<_, Self>(rhs).unsafe_into();
}
fn div_inner<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(self, rhs: RHS) -> OUT::Denormal {
self.div_rem_inner::<_, OUT>(rhs).unwrap().0
}
unsafe fn div_assign_inner<RHS: BigInt<{ BASE }>>(&mut self, rhs: RHS) {
*self = self
.clone()
.div_rem_inner::<_, Self>(rhs)
.unwrap()
.0
.unsafe_into();
}
fn from_str_inner(s: &str) -> Result<Self::Denormal, BigIntError> {
Self::parse(s, STANDARD_ALPHABET).map_err(BigIntError::ParseFailed)
}
fn from_iter_inner<T: IntoIterator<Item = Digit>>(iter: T) -> Self::Denormal {
let mut builder = Self::Builder::new();
for digit in iter {
builder.push_back(digit);
}
builder.into()
}
fn from_u128_inner(mut value: u128) -> Self::Denormal {
let base = BASE as u128;
let mut result = Self::Builder::new();
while value >= base {
let (new_value, rem) = (value / base, value % base);
value = new_value;
result.push_front(rem as Digit);
}
result.push_front(value as Digit);
result.into()
}
fn from_i128_inner(value: i128) -> Self::Denormal {
if value < 0 {
-Self::from_u128_inner((-value) as u128)
} else {
Self::from_u128_inner(value as u128)
}
}
fn into_u128_inner(self) -> u128 {
if self.sign() == Negative {
panic!("uint conversion with underflow");
}
let mut total: u128 = 0;
let mut place: u128 = 0;
for digit in self.into_iter().rev() {
place = if place == 0 { 1 } else { place * BASE as u128 };
total += (digit as u128) * place;
}
total
}
fn into_i128_inner(self) -> i128 {
let mut total: i128 = 0;
let mut place: i128 = 0;
let sign = self.sign();
for digit in self.into_iter().rev() {
place = if place == 0 { 1 } else { place * BASE as i128 };
total += (digit as i128) * place;
}
if sign == Negative {
total = -total;
}
total
}
fn len(&self) -> usize;
fn get_digit(&self, digit: usize) -> Option<Digit>;
fn set_digit(&mut self, digit: usize, value: Digit);
fn zero() -> Self;
fn is_zero(&self) -> bool {
self.iter().all(|digit| digit == 0)
}
fn sign(&self) -> Sign;
fn with_sign(self, sign: Sign) -> Self;
fn set_sign(&mut self, sign: Sign);
fn push_back(&mut self, digit: Digit);
unsafe fn push_front(&mut self, digit: Digit);
unsafe fn pop_back(&mut self) -> Option<Digit>;
unsafe fn pop_front(&mut self) -> Option<Digit>;
fn shr_inner(mut self, amount: usize) -> Self::Denormal {
unsafe {
self.shr_assign_inner(amount);
}
self.into()
}
unsafe fn shr_assign_inner(&mut self, amount: usize) {
*self = self.clone().shr_inner(amount).unsafe_into();
}
fn shl_inner(mut self, amount: usize) -> Self::Denormal {
unsafe {
self.shl_assign_inner(amount);
}
self.into()
}
unsafe fn shl_assign_inner(&mut self, amount: usize) {
*self = self.clone().shl_inner(amount).unsafe_into();
}
fn div_rem_inner<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(
mut self,
mut rhs: RHS,
) -> Result<(OUT::Denormal, OUT::Denormal), BigIntError> {
if rhs.is_zero() {
return Err(BigIntError::DivisionByZero);
}
if rhs.len() > self.len() {
return Ok((OUT::Denormal::zero(), self.convert_inner::<BASE, OUT>()));
}
let mut shift = 0;
while let (Some(0), Some(0)) = (self.get_back(1), rhs.get_back(1)) {
unsafe {
self.shr_assign_inner(1);
rhs.shr_assign_inner(1);
}
shift += 1;
}
let sign = self.sign() * rhs.sign();
self.set_sign(Positive);
rhs.set_sign(Positive);
let quot_digits = self.len() - rhs.len() + 1;
let mut quot = OUT::Builder::new();
let mut prod = Self::zero();
let mut addends = rhs.clone().shl_inner(quot_digits - 1).addends().memo();
for _ in 0..quot_digits {
let mut digit_value = 0;
for index in (0..Self::BITS_PER_DIGIT).rev() {
let power = 1 << index;
let new_prod = unsafe {
prod.clone()
.add_inner::<_, Self>(addends.get(index).unwrap().clone())
.unsafe_into()
};
if new_prod <= self {
digit_value += power;
prod = new_prod;
}
unsafe {
addends.get_mut(index).unwrap().shr_assign_inner(1);
}
}
quot.push_back(digit_value);
}
let mut rem: OUT::Denormal = self.sub_inner::<_, OUT>(prod);
if !rem.is_zero() {
rem.set_sign(sign);
}
unsafe {
rem.shl_assign_inner(shift);
}
Ok((quot.with_sign(sign).into(), rem))
}
fn div_rem<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(
self,
rhs: RHS,
) -> Result<(OUT, OUT), BigIntError> {
self.div_rem_inner::<RHS, OUT>(rhs)
.map(|(q, r): (OUT::Denormal, OUT::Denormal)| (q.unwrap(), r.unwrap()))
}
fn exp_inner<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(
self,
mut rhs: RHS,
) -> Result<OUT::Denormal, BigIntError> {
if rhs < RHS::zero() {
return Err(BigIntError::NegativeExponentiation);
}
let mut mullands = self.mullands().memo();
let mut addends = RHS::from(1).addends().memo();
let mut power = 0;
let mut result: OUT = 1.into();
while rhs.cmp_inner(addends.get(power).unwrap()).is_ge() {
rhs -= addends.get(power).unwrap().clone();
unsafe {
result.mul_assign_inner(mullands.get(power).unwrap().clone());
}
power += 1;
}
for mulland_index in (0..power).rev() {
let comparison = rhs.cmp_inner(addends.get(mulland_index).unwrap());
if comparison.is_ge() {
rhs -= addends.get(mulland_index).unwrap().clone();
unsafe {
result.mul_assign_inner(mullands.get(mulland_index).unwrap().clone());
}
if comparison.is_eq() {
break;
}
}
}
Ok(result.into())
}
fn exp<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(
self,
rhs: RHS,
) -> Result<OUT, BigIntError> {
self.exp_inner::<RHS, OUT>(rhs).map(|x| x.unwrap())
}
fn log_inner<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(
self,
rhs: RHS,
) -> Result<OUT::Denormal, BigIntError> {
if self <= Self::zero() {
return Err(BigIntError::NonPositiveLogarithm);
}
if rhs <= 1.into() {
return Err(BigIntError::LogOfSmallBase);
}
let mut mullands = rhs.mullands().memo();
let mut addends = OUT::from(1).addends().memo();
let mut power = 0;
let mut base: Self = 1.into();
let mut exp = OUT::zero();
let result = 'outer: {
loop {
let next_base: Self = unsafe {
base.clone()
.mul_inner::<RHS, Self>(mullands.get(power).unwrap().clone())
.unsafe_into()
};
let comparison = next_base.cmp_inner(&self);
if comparison.is_le() {
exp += addends.get(power).unwrap().clone();
base = next_base;
power += 1;
}
if comparison.is_ge() {
break;
}
}
for mulland_index in (0..power).rev() {
let next_base: Self = unsafe {
base.clone()
.mul_inner::<RHS, Self>(mullands.get(mulland_index).unwrap().clone())
.unsafe_into()
};
let comparison = next_base.cmp_inner(&self);
if comparison.is_le() {
exp += addends.get(mulland_index).unwrap().clone();
if comparison.is_eq() {
break 'outer exp;
}
base = next_base;
}
}
exp
};
Ok(result.into())
}
fn log<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(
self,
rhs: RHS,
) -> Result<OUT, BigIntError> {
self.log_inner::<RHS, OUT>(rhs).map(|x| x.unwrap())
}
fn root_inner<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(
self,
rhs: RHS,
) -> Result<OUT::Denormal, BigIntError> {
if self < Self::zero() {
return Err(BigIntError::NegativeRoot);
}
if self.is_zero() {
return Ok(OUT::Denormal::zero());
}
if rhs <= 1.into() {
return Err(BigIntError::SmallRoot);
}
let result_digits = (self.len() / Into::<usize>::into(rhs.clone())).max(1);
let mut result = OUT::from(1).shl_inner(result_digits);
result.set_digit(0, 0);
'outer: for i in 0..result.len() {
let mut digit_value = 0;
for index in (0..Self::BITS_PER_DIGIT).rev() {
let power = 1 << index;
result.set_digit(i, digit_value + power);
let new_exp: Self = result.clone().exp(rhs.clone()).unwrap();
let comparison = new_exp.cmp_inner(&self);
if comparison.is_le() {
digit_value += power;
if comparison.is_eq() {
break 'outer;
}
}
}
result.set_digit(i, digit_value);
}
Ok(result.into())
}
fn root<RHS: BigInt<{ BASE }>, OUT: BigInt<{ BASE }>>(
self,
rhs: RHS,
) -> Result<OUT, BigIntError> {
self.root_inner::<RHS, OUT>(rhs).map(|x| x.unwrap())
}
fn is_even(&self) -> bool {
if BASE % 2 == 0 {
self.get_digit(self.len() - 1)
.map(|d| d % 2 == 0)
.unwrap_or(true)
} else {
self.iter().filter(|d| d % 2 == 1).count() % 2 == 0
}
}
fn iter<'a>(&'a self) -> BigIntIter<'a, BASE, Self> {
BigIntIter {
index: 0,
back_index: self.len(),
int: self,
}
}
fn normalized(mut self) -> Self {
self.normalize();
self
}
fn normalize(&mut self) {
*self = self.clone().normalized();
}
fn display(&self, alphabet: &str) -> Result<String, BigIntError> {
let digits = self
.iter()
.map(|digit| {
alphabet
.chars()
.nth(digit as usize)
.ok_or(BigIntError::BaseTooHigh(BASE, alphabet.len()))
})
.collect::<Result<String, _>>()?;
if self.sign() == Negative {
Ok(format!("-{digits}"))
} else {
Ok(digits)
}
}
fn parse(value: &str, alphabet: &str) -> Result<Self::Denormal, ParseError> {
let mut builder = Self::Builder::new();
let (sign, chars) = match value.chars().next() {
Some('-') => (Negative, value.chars().skip(1)),
Some(_) => (Positive, value.chars().skip(0)),
None => return Err(ParseError::NotEnoughCharacters),
};
for char in chars {
match alphabet.chars().position(|c| c == char) {
Some(pos) => {
if pos >= BASE {
return Err(ParseError::DigitTooLarge(char, pos, BASE));
} else {
builder.push_back(pos as Digit);
}
}
None => return Err(ParseError::UnrecognizedCharacter(char)),
}
}
if builder.is_empty() {
Err(ParseError::NotEnoughCharacters)
} else {
Ok(builder.with_sign(sign).into())
}
}
fn convert_inner<const TO: usize, OUT: BigInt<{ TO }>>(mut self) -> OUT::Denormal {
let to = TO as Digit;
let base = BASE as Digit;
let sign = self.sign();
let mut result = OUT::Builder::new();
if BASE == TO {
for digit in self {
result.push_back(digit);
}
} else if let Some(power) = is_power(BASE, TO) {
for mut from_digit in self.into_iter().rev() {
for _ in 0..power {
result.push_front(from_digit % to);
if from_digit >= to {
from_digit /= to;
} else {
from_digit = 0;
}
}
}
} else if let Some(power) = is_power(TO, BASE) {
let mut iter = self.into_iter().rev();
loop {
let mut to_digit = 0;
let mut done = false;
let mut place = 1;
for _ in 0..power {
if let Some(from_digit) = iter.next() {
to_digit += from_digit * place;
place *= base;
} else {
done = true;
break;
}
}
result.push_front(to_digit);
if done {
break;
}
}
} else {
self.set_sign(Positive);
let to_base: Self = to.into();
while self >= to_base {
let (quot, rem) = self.div_rem_inner::<_, Self>(to_base.clone()).unwrap();
self = unsafe { quot.unsafe_into() }.normalized();
result.push_front(Into::<Digit>::into(rem));
}
result.push_front(Into::<Digit>::into(self));
}
result.with_sign(sign).into()
}
fn convert<const TO: usize, OUT: BigInt<{ TO }>>(self) -> OUT {
self.convert_inner::<TO, OUT>().unwrap()
}
fn cmp_magnitude<RHS: BigInt<{ BASE }>>(&self, rhs: &RHS) -> Ordering {
for i in (1..=self.len().max(rhs.len())).rev() {
match (self.get_back(i), rhs.get_back(i)) {
(Some(1..), None) => return Ordering::Greater,
(None, Some(1..)) => return Ordering::Less,
(self_digit, rhs_digit) => match self_digit
.unwrap_or_default()
.cmp(&rhs_digit.unwrap_or_default())
{
Ordering::Equal => {}
ordering => return ordering,
},
}
}
Ordering::Equal
}
fn abs(self) -> Self {
self.with_sign(Positive)
}
}
struct AddendSet<const BASE: usize, B: BigInt<{ BASE }>> {
addend: B,
}
trait Addends<const BASE: usize, B: BigInt<{ BASE }>> {
fn addends(self) -> AddendSet<BASE, B>;
}
impl<const BASE: usize, B: BigInt<{ BASE }>> Addends<BASE, B> for B {
fn addends(self) -> AddendSet<BASE, B> {
AddendSet { addend: self }
}
}
impl<const BASE: usize, B: BigInt<{ BASE }>> Iterator for AddendSet<BASE, B> {
type Item = B;
fn next(&mut self) -> Option<Self::Item> {
let next_addend = self.addend.clone();
self.addend += self.addend.clone();
Some(next_addend)
}
}
struct MullandSet<const BASE: usize, B: BigInt<{ BASE }>> {
mulland: B,
}
trait Mullands<const BASE: usize, B: BigInt<{ BASE }>> {
fn mullands(self) -> MullandSet<BASE, B>;
}
impl<const BASE: usize, B: BigInt<{ BASE }>> Mullands<BASE, B> for B {
fn mullands(self) -> MullandSet<BASE, B> {
MullandSet { mulland: self }
}
}
impl<const BASE: usize, B: BigInt<{ BASE }>> Iterator for MullandSet<BASE, B> {
type Item = B;
fn next(&mut self) -> Option<Self::Item> {
let next_mulland = self.mulland.clone();
self.mulland *= self.mulland.clone();
Some(next_mulland)
}
}
struct NAddendSet<const BASE: usize, B: BigInt<{ BASE }>> {
addend: B,
factor: B,
}
trait NAddends<const BASE: usize, B: BigInt<{ BASE }>> {
fn n_addends(self, factor: B) -> NAddendSet<BASE, B>;
}
impl<const BASE: usize, B: BigInt<{ BASE }>> NAddends<BASE, B> for B {
fn n_addends(self, factor: B) -> NAddendSet<BASE, B> {
NAddendSet {
addend: self,
factor,
}
}
}
impl<const BASE: usize, B: BigInt<{ BASE }>> Iterator for NAddendSet<BASE, B> {
type Item = B;
fn next(&mut self) -> Option<Self::Item> {
let next_mulland = self.addend.clone();
self.addend *= self.factor.clone();
Some(next_mulland)
}
}
struct IterMemo<I: Iterator> {
memo: Vec<I::Item>,
iter: I,
exhausted: bool,
}
impl<I: Iterator> IterMemo<I> {
fn get(&mut self, index: usize) -> Option<&I::Item> {
while self.memo.len() <= index && !self.exhausted {
self.store_next();
}
self.memo.get(index)
}
fn get_mut(&mut self, index: usize) -> Option<&mut I::Item> {
while self.memo.len() <= index && !self.exhausted {
self.store_next();
}
self.memo.get_mut(index)
}
fn store_next(&mut self) {
if let Some(item) = self.iter.next() {
self.memo.push(item);
} else {
self.exhausted = true;
}
}
}
impl<I: Iterator> From<I> for IterMemo<I> {
fn from(value: I) -> Self {
IterMemo {
memo: Vec::new(),
iter: value,
exhausted: false,
}
}
}
trait ToMemo: Iterator + Sized {
fn memo(self) -> IterMemo<Self> {
self.into()
}
}
impl<I: Iterator> ToMemo for I {}
pub trait BigIntBuilder<const BASE: usize>
where
Self: std::fmt::Debug,
{
fn new() -> Self;
fn push_front(&mut self, digit: Digit);
fn push_back(&mut self, digit: Digit);
fn is_empty(&self) -> bool;
fn with_sign(self, sign: Sign) -> Self;
}
pub trait UnsafeInto<T> {
unsafe fn unsafe_into(self) -> T;
}
impl<T> UnsafeInto<T> for T {
unsafe fn unsafe_into(self) -> T {
self
}
}
pub trait Unwrap<T> {
fn unwrap(self) -> T;
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Sign {
Positive,
Negative,
}
impl Neg for Sign {
type Output = Sign;
fn neg(self) -> Self::Output {
match self {
Positive => Negative,
Negative => Positive,
}
}
}
impl Mul for Sign {
type Output = Sign;
fn mul(self, rhs: Self) -> Self::Output {
if self == rhs {
Positive
} else {
Negative
}
}
}
pub struct BigIntIntoIter<const BASE: usize, B: BigInt<{ BASE }>>(B);
impl<const BASE: usize, B: BigInt<{ BASE }>> Iterator for BigIntIntoIter<BASE, B> {
type Item = Digit;
fn next(&mut self) -> Option<Self::Item> {
unsafe { self.0.pop_front() }
}
}
impl<const BASE: usize, B: BigInt<{ BASE }>> DoubleEndedIterator for BigIntIntoIter<BASE, B> {
fn next_back(&mut self) -> Option<Self::Item> {
unsafe { self.0.pop_back() }
}
}
pub struct BigIntIter<'a, const BASE: usize, B: BigInt<{ BASE }>> {
index: usize,
back_index: usize,
int: &'a B,
}
impl<'a, const BASE: usize, B: BigInt<{ BASE }>> Iterator for BigIntIter<'_, BASE, B> {
type Item = Digit;
fn next(&mut self) -> Option<Self::Item> {
(self.index < self.back_index)
.then_some(&mut self.index)
.and_then(|index| {
*index += 1;
self.int.get_digit(*index - 1)
})
}
}
impl<'a, const BASE: usize, B: BigInt<{ BASE }>> DoubleEndedIterator for BigIntIter<'_, BASE, B> {
fn next_back(&mut self) -> Option<Self::Item> {
(self.back_index > self.index)
.then_some(&mut self.back_index)
.and_then(|index| {
*index -= 1;
self.int.get_digit(*index)
})
}
}
pub(crate) fn is_power(mut x: usize, y: usize) -> Option<usize> {
if x == 1 {
Some(0)
} else {
let mut power = 1;
loop {
if x % y != 0 {
return None;
}
match x.cmp(&y) {
Ordering::Equal => return Some(power),
Ordering::Less => return None,
Ordering::Greater => {
power += 1;
x /= y;
}
}
}
}
}
pub(crate) const fn bits_per_digit(base: usize) -> usize {
let mut bits = 1;
let mut max_base_of_bits = 2;
while max_base_of_bits < base {
bits += 1;
max_base_of_bits <<= 1;
}
bits
}