use crate::helpers;
#[cfg(feature = "traits")]
use crate::traits::decl::Idx;
#[cfg(feature = "traits")]
use core::range::Range;
use std::{
fmt::{Debug, Display},
iter::{Product, Step, Sum},
ops::{
Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div,
DivAssign, Mul, MulAssign, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
SubAssign,
},
};
#[derive(Clone, Debug)]
pub struct UInt {
prec: u64,
value: Option<Vec<u8>>,
pub dynamic_resizing: bool,
pub dbg_disp_enabled: bool,
}
impl UInt {
pub fn new(initial_value: impl Into<u128>) -> Self {
let value: u128 = initial_value.into();
if value == 0 {
return Self::from_op(8, Some(value)).unwrap();
}
let bits_needed = 128 - value.leading_zeros();
let bits = (((bits_needed + 7) / 8) * 8) as u64;
Self::from_op(bits, Some(value)).unwrap()
}
pub fn with_prec(bits: u64, initial_value: impl Into<u128>) -> Self {
let value: u128 = initial_value.into();
if value == 0 {
return Self::from_op(bits, Some(value)).unwrap();
}
Self::from_op(bits, Some(value)).unwrap()
}
pub fn from_op(bits: u64, initial_value: Option<impl Into<u128>>) -> Result<Self, IntError> {
let initial_value = Self::parse_op(initial_value);
if initial_value.is_some() {
let check = initial_value.as_ref().unwrap();
if (check.len() * 8) as u64 > bits {
println!("error here");
return Err(IntError::Overflow);
}
}
Ok(Self {
prec: bits,
value: initial_value,
dynamic_resizing: true,
dbg_disp_enabled: false,
})
}
pub fn parse_op(val: Option<impl Into<u128>>) -> Option<Vec<u8>> {
return if val.is_none() {
None
} else {
Some(Self::parse(val.unwrap()))
};
}
pub fn parse(val: impl Into<u128>) -> Vec<u8> {
let val: u128 = val.into();
if val == 0 {
return vec![0];
}
let mut bytes = Vec::new();
let mut remaining = val;
while remaining > 0 {
bytes.push((remaining & 0xFF) as u8);
remaining >>= 8;
}
bytes.reverse();
bytes
}
pub fn from_vec(bits: u64, initial_value: Option<Vec<u8>>) -> Result<Self, IntError> {
if initial_value.is_some() {
let check = initial_value.as_ref().unwrap();
if (check.len() * 8) as u64 > bits {
return Err(IntError::Overflow);
}
}
Ok(Self {
prec: bits,
value: initial_value,
dynamic_resizing: true,
dbg_disp_enabled: false,
})
}
pub fn compare_bytes(a: &[u8], b: &[u8]) -> std::cmp::Ordering {
if a.len() != b.len() {
return a.len().cmp(&b.len());
}
for (x, y) in a.iter().zip(b.iter()) {
match x.cmp(y) {
std::cmp::Ordering::Equal => continue,
other => return other,
}
}
std::cmp::Ordering::Equal
}
pub fn subtract_with_borrow(a: &mut [u8], b: &[u8]) -> bool {
let mut borrow = 0i16;
for i in (0..a.len()).rev() {
let ai = a[i] as i16;
let bi = if i < b.len() { b[i] as i16 } else { 0 };
let diff = ai - bi - borrow;
if diff < 0 {
a[i] = (diff + 256) as u8;
borrow = 1;
} else {
a[i] = diff as u8;
borrow = 0;
}
}
borrow == 0
}
pub fn increase_precision_to(&self, required_bits: u64) -> Result<Self, IntError> {
if !self.dynamic_resizing {
return Err(IntError::NoDyn);
}
let new_prec = (((required_bits + 7) / 8) * 8) as u64;
Ok(Self {
prec: new_prec,
value: self.value.clone(),
dynamic_resizing: self.dynamic_resizing,
dbg_disp_enabled: self.dbg_disp_enabled,
})
}
pub fn zero(bits: u64) -> Self {
Self::with_prec(bits, 0u128)
}
pub fn one(bits: u64) -> Self {
Self::with_prec(bits, 1u128)
}
pub fn two(bits: u64) -> Self {
Self::with_prec(bits, 2u128)
}
pub fn ten(bits: u64) -> Self {
Self::with_prec(bits, 10u128)
}
pub fn max(bits: u64) -> Self {
let bytes = (bits as u128 + 7u128) / 8u128; let mut vec = vec![255u8; bytes as usize];
if bits % 8 != 0 {
let excess_bits = 8 - (bits % 8);
vec[0] &= 0xFF >> excess_bits;
}
Self::from_vec(bits, Some(vec)).unwrap()
}
pub fn get_internal_value_ref(&self) -> &Option<Vec<u8>> {
&self.value
}
pub fn get_internal_value_ref_mut(&mut self) -> &mut Option<Vec<u8>> {
&mut self.value
}
pub fn pow(&self, exp: u64) -> Self {
if exp == 0 {
return UInt::new(1u128);
}
let orig = self.clone();
let mut orig2 = self.clone();
for _ in 0..exp - 1 {
orig2 *= orig.clone()
}
orig2
}
pub fn sci(&self, exp: u64) -> Self {
if exp == 0 {
return self.clone();
}
let orig = self.clone();
let mul = Self::ten(self.prec).pow(exp);
orig.mul(mul)
}
#[cfg(not(feature = "better_rand"))]
pub fn random(bits: u64) -> Self {
let mut rng = random::LCG::new(
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos() as u64,
);
let bytes = (bits + 7) / 8;
let mut vec = Vec::with_capacity(bytes as usize);
for i in 0..bytes {
let byte = if i == bytes - 1 && bits % 8 != 0 {
rng.next_u8() & ((1 << (bits % 8)) - 1)
} else {
rng.next_u8()
};
vec.push(byte);
}
Self::from_vec(bits, Some(vec)).unwrap()
}
#[cfg(feature = "better_rand")]
pub fn random(bits: u64) -> Self {
use rand::{thread_rng, RngCore};
let mut rng = thread_rng();
let bytes = (bits + 7) / 8;
let mut vec = Vec::with_capacity(bytes as usize);
for i in 0..bytes {
let byte = if i == bytes - 1 && bits % 8 != 0 {
rng.next_u32() as u8 & ((1 << (bits % 8)) - 1)
} else {
rng.next_u32() as u8
};
vec.push(byte);
}
Self::from_vec(bits, Some(vec)).unwrap()
}
pub fn random_in_range(bits: u64, min: Self, max: Self) -> Self {
assert!(min <= max, "min must not exceed max");
let range = max.clone() - min.clone() + Self::one(bits);
let mut attempts = 0;
loop {
attempts += 1;
if attempts > 1000 {
return min.clone() + (Self::random(bits) % range.clone());
}
let random = Self::random(bits);
if random >= min && random <= max {
return random;
}
}
}
pub fn sqrt(n: UInt) -> f64 {
if n.value.is_none() {
return f64::NAN;
}
let bytes = n.value.unwrap();
if bytes.iter().all(|&b| b == 0) {
return 0.0;
}
let mut value: f64 = 0.0;
for &byte in bytes.iter() {
value = value * 256.0 + byte as f64;
}
let mut x = value;
let mut prev_x;
loop {
prev_x = x;
x = (x + value / x) / 2.0;
if (x - prev_x).abs() < 1e-10 {
break;
}
}
x
}
pub fn log(&self, base: &Self) -> Option<f64> {
if self.value.is_none() || base.value.is_none() {
return None;
}
let n = self.value.as_ref().unwrap();
let b = base.value.as_ref().unwrap();
if n.iter().all(|&x| x == 0) {
return None;
}
if n.len() == 1 && n[0] == 1 {
return Some(0.0);
}
if b.len() == 1 && b[0] == 1 || b.iter().all(|&x| x == 0) {
return None;
}
let mut n_val: f64 = 0.0;
for &byte in n.iter() {
n_val = n_val * 256.0 + byte as f64;
}
let mut b_val: f64 = 0.0;
for &byte in b.iter() {
b_val = b_val * 256.0 + byte as f64;
}
Some(n_val.ln() / b_val.ln())
}
pub fn ln(&self) -> Option<f64> {
if self.value.is_none() {
return None;
}
let n = self.value.as_ref().unwrap();
if n.iter().all(|&x| x == 0) {
return None;
}
if n.len() == 1 && n[0] == 1 {
return Some(0.0);
}
let mut value: f64 = 0.0;
for &byte in n.iter() {
value = value * 256.0 + byte as f64;
}
Some(value.ln())
}
pub fn log2(&self) -> Option<f64> {
self.log(&Self::two(self.prec))
}
pub fn log10(&self) -> Option<f64> {
self.log(&Self::ten(self.prec))
}
}
impl Default for UInt {
fn default() -> Self {
Self::zero(64) }
}
impl Add for UInt {
type Output = UInt;
fn add(self, rhs: Self) -> Self::Output {
if self.value.is_none() || rhs.value.is_none() {
return Self::from_vec(self.prec, None).unwrap();
}
let mut lhs = self.value.unwrap();
let mut rhs = rhs.value.unwrap();
lhs.reverse();
rhs.reverse();
let len = lhs.len().max(rhs.len());
let mut result = Vec::with_capacity(len + 1); let mut carry = 0u8;
for i in 0..len {
let lhs_byte = if i < lhs.len() { lhs[i] } else { 0 };
let rhs_byte = if i < rhs.len() { rhs[i] } else { 0 };
let sum = u16::from(lhs_byte) + u16::from(rhs_byte) + u16::from(carry);
result.push((sum & 0xFF) as u8); carry = (sum >> 8) as u8; }
if carry > 0 {
result.push(carry);
}
result.reverse();
let required_bits = (result.len() * 8) as u64;
if required_bits > self.prec {
if self.dynamic_resizing {
return Self::from_vec(required_bits, Some(result)).unwrap();
} else {
panic!("UUInt: Addition result exceeds maximum bits allowed");
}
}
Self::from_vec(self.prec, Some(result)).unwrap()
}
}
impl Sub for UInt {
type Output = UInt;
fn sub(self, rhs: Self) -> Self::Output {
if self.value.is_none() || rhs.value.is_none() {
return Self::from_vec(self.prec, None).unwrap();
}
let mut lhs = self.value.unwrap();
let mut rhs = rhs.value.unwrap();
lhs.reverse();
rhs.reverse();
let len = lhs.len().max(rhs.len());
let mut result = Vec::with_capacity(len);
let mut borrow = 0i16;
for i in 0..len {
let lhs_byte = if i < lhs.len() { lhs[i] as i16 } else { 0 };
let rhs_byte = if i < rhs.len() { rhs[i] as i16 } else { 0 };
let mut diff = lhs_byte - rhs_byte - borrow;
if diff < 0 {
diff += 256;
borrow = 1;
} else {
borrow = 0;
}
result.push(diff as u8);
}
if borrow > 0 {
panic!("UUInt: Subtraction result would be negative");
}
while result.len() > 1 && result.last() == Some(&0) {
result.pop();
}
result.reverse();
Self::from_vec(self.prec, Some(result)).unwrap()
}
}
impl Mul for UInt {
type Output = UInt;
fn mul(self, rhs: Self) -> Self::Output {
if self.value.is_none() || rhs.value.is_none() {
return Self::from_vec(self.prec, None).unwrap();
}
let lhs = self.value.unwrap();
let rhs = rhs.value.unwrap();
let mut result = vec![0u8; lhs.len() + rhs.len()];
let mut lhs_rev = lhs.clone();
let mut rhs_rev = rhs.clone();
lhs_rev.reverse();
rhs_rev.reverse();
for (i, &lhs_byte) in lhs_rev.iter().enumerate() {
let mut carry = 0u16;
for (j, &rhs_byte) in rhs_rev.iter().enumerate() {
let pos = i + j;
let total =
u16::from(lhs_byte) * u16::from(rhs_byte) + u16::from(result[pos]) + carry;
result[pos] = (total & 0xFF) as u8;
carry = total >> 8;
}
let mut carry_pos = i + rhs_rev.len();
while carry > 0 && carry_pos < result.len() {
let total = u16::from(result[carry_pos]) + carry;
result[carry_pos] = (total & 0xFF) as u8;
carry = total >> 8;
carry_pos += 1;
}
}
result.reverse();
while result.len() > 1 && result[0] == 0 {
result.remove(0);
}
let required_bits = (result.len() * 8) as u64;
if required_bits > self.prec {
if self.dynamic_resizing {
return Self::from_vec(required_bits, Some(result)).unwrap();
} else {
panic!("UUInt: Multiplication result exceeds maximum bits allowed");
}
}
Self::from_vec(self.prec, Some(result)).unwrap()
}
}
impl Div for UInt {
type Output = UInt;
fn div(self, rhs: Self) -> Self::Output {
if self.value.is_none() || rhs.value.is_none() {
return Self::from_vec(self.prec, None).unwrap();
}
let dividend = self.value.unwrap();
let divisor = rhs.value.unwrap();
if divisor.iter().all(|&x| x == 0) {
return Self::max(self.prec);
}
if dividend.len() < divisor.len() || (dividend.len() == divisor.len() && dividend < divisor)
{
return Self::from_vec(self.prec, Some(vec![0])).unwrap();
}
if dividend == divisor {
return Self::from_vec(self.prec, Some(vec![1])).unwrap();
}
let mut quotient = Vec::new();
let mut remainder = dividend.clone();
let divisor_len = divisor.len();
let mut pos = 0;
while pos < remainder.len() - divisor_len + 1 {
let mut trial;
let mut left = 0u8;
let mut right = 255u8;
while left <= right {
trial = (left + right) / 2;
let mut temp = divisor.clone();
for byte in &mut temp {
*byte = byte.wrapping_mul(trial);
}
let mut aligned_temp = vec![0u8; pos];
aligned_temp.extend_from_slice(&temp);
if Self::subtract_with_borrow(&mut remainder.clone(), &aligned_temp) {
left = trial + 1;
} else {
right = trial - 1;
}
}
trial = right;
quotient.push(trial);
let mut temp = divisor.clone();
for byte in &mut temp {
*byte = byte.wrapping_mul(trial);
}
let mut aligned_temp = vec![0u8; pos];
aligned_temp.extend_from_slice(&temp);
Self::subtract_with_borrow(&mut remainder, &aligned_temp);
pos += 1;
}
while quotient.len() > 1 && quotient[0] == 0 {
quotient.remove(0);
}
Self::from_vec(self.prec, Some(quotient)).unwrap()
}
}
impl Rem for UInt {
type Output = UInt;
fn rem(self, rhs: Self) -> Self::Output {
if self.value.is_none() || rhs.value.is_none() {
return Self::from_vec(self.prec, None).unwrap();
}
let dividend = self.value.unwrap();
let divisor = rhs.value.unwrap();
if divisor.iter().all(|&x| x == 0) {
return Self::with_prec(self.prec, 0u128);
}
if dividend.len() < divisor.len() || (dividend.len() == divisor.len() && dividend < divisor)
{
return Self::from_vec(self.prec, Some(dividend)).unwrap();
}
let mut remainder = dividend.clone();
while Self::compare_bytes(&remainder, &divisor) != std::cmp::Ordering::Less {
let temp = divisor.clone();
if !Self::subtract_with_borrow(&mut remainder, &temp) {
break;
}
}
while remainder.len() > 1 && remainder[0] == 0 {
remainder.remove(0);
}
Self::from_vec(self.prec, Some(remainder)).unwrap()
}
}
impl BitAnd for UInt {
type Output = UInt;
fn bitand(self, rhs: Self) -> Self::Output {
if self.value.is_none() || rhs.value.is_none() {
return Self::from_vec(self.prec, None).unwrap();
}
let lhs = self.value.unwrap();
let rhs = rhs.value.unwrap();
let len = lhs.len().max(rhs.len());
let mut result = Vec::with_capacity(len);
for i in 0..len {
let lhs_byte = if i < lhs.len() { lhs[i] } else { 0 };
let rhs_byte = if i < rhs.len() { rhs[i] } else { 0 };
result.push(lhs_byte & rhs_byte);
}
while result.len() > 1 && result[0] == 0 {
result.remove(0);
}
Self::from_vec(self.prec, Some(result)).unwrap()
}
}
impl BitOr for UInt {
type Output = UInt;
fn bitor(self, rhs: Self) -> Self::Output {
if self.value.is_none() || rhs.value.is_none() {
return Self::from_vec(self.prec, None).unwrap();
}
let lhs = self.value.unwrap();
let rhs = rhs.value.unwrap();
let len = lhs.len().max(rhs.len());
let mut result = Vec::with_capacity(len);
for i in 0..len {
let lhs_byte = if i < lhs.len() { lhs[i] } else { 0 };
let rhs_byte = if i < rhs.len() { rhs[i] } else { 0 };
result.push(lhs_byte | rhs_byte);
}
let required_bits = (result.len() * 8) as u64;
if required_bits > self.prec {
if self.dynamic_resizing {
return Self::from_vec(required_bits, Some(result)).unwrap();
} else {
panic!("UUInt: BitOr result exceeds maximum bits allowed");
}
}
Self::from_vec(self.prec, Some(result)).unwrap()
}
}
impl BitXor for UInt {
type Output = UInt;
fn bitxor(self, rhs: Self) -> Self::Output {
if self.value.is_none() || rhs.value.is_none() {
return Self::from_vec(self.prec, None).unwrap();
}
let lhs = self.value.unwrap();
let rhs = rhs.value.unwrap();
let len = lhs.len().max(rhs.len());
let mut result = Vec::with_capacity(len);
for i in 0..len {
let lhs_byte = if i < lhs.len() { lhs[i] } else { 0 };
let rhs_byte = if i < rhs.len() { rhs[i] } else { 0 };
result.push(lhs_byte ^ rhs_byte);
}
while result.len() > 1 && result[0] == 0 {
result.remove(0);
}
let required_bits = (result.len() * 8) as u64;
if required_bits > self.prec {
if self.dynamic_resizing {
return Self::from_vec(required_bits, Some(result)).unwrap();
} else {
panic!("UUInt: BitXor result exceeds maximum bits allowed");
}
}
Self::from_vec(self.prec, Some(result)).unwrap()
}
}
impl Shl<u64> for UInt {
type Output = UInt;
fn shl(self, rhs: u64) -> Self::Output {
if self.value.is_none() {
return Self::from_vec(self.prec, None).unwrap();
}
let mut value = self.value.unwrap();
let bytes_to_shift = (rhs / 8) as usize;
let bits_to_shift = (rhs % 8) as u64;
let mut result = vec![0; bytes_to_shift];
result.extend_from_slice(&value);
value = result;
if bits_to_shift > 0 {
let mut carry = 0u8;
for byte in value.iter_mut().rev() {
let new_carry = *byte >> (8 - bits_to_shift);
*byte = (*byte << bits_to_shift) | carry;
carry = new_carry;
}
if carry > 0 {
value.insert(0, carry);
}
}
let required_bits = (value.len() * 8) as u64;
if required_bits > self.prec {
if self.dynamic_resizing {
return Self::from_vec(required_bits, Some(value)).unwrap();
} else {
panic!("UUInt: Left shift result exceeds maximum bits allowed");
}
}
Self::from_vec(self.prec, Some(value)).unwrap()
}
}
impl Shr<u64> for UInt {
type Output = UInt;
fn shr(self, rhs: u64) -> Self::Output {
if self.value.is_none() {
return Self::from_vec(self.prec, None).unwrap();
}
let value = self.value.unwrap();
let bytes_to_shift = (rhs / 8) as usize;
let bits_to_shift = (rhs % 8) as u64;
if bytes_to_shift >= value.len() {
return Self::from_vec(self.prec, Some(vec![0])).unwrap();
}
let mut result = value[bytes_to_shift..].to_vec();
if bits_to_shift > 0 {
let mut carry = 0u8;
for byte in result.iter_mut() {
let new_carry = *byte << (8 - bits_to_shift);
*byte = (*byte >> bits_to_shift) | carry;
carry = new_carry;
}
}
while result.len() > 1 && result[0] == 0 {
result.remove(0);
}
Self::from_vec(self.prec, Some(result)).unwrap()
}
}
impl Not for UInt {
type Output = UInt;
fn not(self) -> Self::Output {
if self.value.is_none() {
return Self::from_vec(self.prec, None).unwrap();
}
let mut bytes = self.value.unwrap();
for byte in bytes.iter_mut() {
*byte = !*byte;
}
if self.prec % 8 != 0 {
let excess_bits = 8 - (self.prec % 8);
bytes[0] &= 0xFF >> excess_bits;
}
Self::from_vec(self.prec, Some(bytes)).unwrap()
}
}
#[cfg(feature = "traits")]
impl Idx<usize, bool> for UInt {
fn index(&self, idx: usize) -> bool {
return self.gen_bin_disp().chars().collect::<Vec<char>>()[idx] == '1';
}
}
#[cfg(feature = "traits")]
impl Idx<Range<usize>, Vec<bool>> for UInt {
fn index(&self, idx: Range<usize>) -> Vec<bool> {
return self.gen_bin_disp()[idx]
.chars()
.map(|c| match c {
'0' => false,
'1' => true,
_ => unreachable!(),
})
.collect();
}
}
impl AddAssign for UInt {
fn add_assign(&mut self, rhs: Self) {
*self = self.clone() + rhs;
}
}
impl SubAssign for UInt {
fn sub_assign(&mut self, rhs: Self) {
*self = self.clone() - rhs;
}
}
impl MulAssign for UInt {
fn mul_assign(&mut self, rhs: Self) {
*self = self.clone() * rhs;
}
}
impl DivAssign for UInt {
fn div_assign(&mut self, rhs: Self) {
*self = self.clone() / rhs;
}
}
impl RemAssign for UInt {
fn rem_assign(&mut self, rhs: Self) {
*self = self.clone() % rhs;
}
}
impl BitAndAssign for UInt {
fn bitand_assign(&mut self, rhs: Self) {
*self = self.clone() & rhs;
}
}
impl BitOrAssign for UInt {
fn bitor_assign(&mut self, rhs: Self) {
*self = self.clone() | rhs;
}
}
impl BitXorAssign for UInt {
fn bitxor_assign(&mut self, rhs: Self) {
*self = self.clone() ^ rhs;
}
}
impl ShlAssign<u64> for UInt {
fn shl_assign(&mut self, rhs: u64) {
*self = self.clone() << rhs;
}
}
impl ShrAssign<u64> for UInt {
fn shr_assign(&mut self, rhs: u64) {
*self = self.clone() >> rhs;
}
}
pub enum IntError {
Overflow,
NoneVal,
NoDyn,
ParseErr(ParseErrKind),
}
#[derive(Debug)]
pub enum ParseErrKind {
InvalidRadix,
InvalidDigit,
Empty,
}
impl Debug for IntError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NoDyn => write!(f, "DynamicResizeDisabled"),
Self::NoneVal => write!(f, "NoneValue"),
Self::Overflow => write!(f, "Overflow"),
Self::ParseErr(e) => write!(f, "ParseError({e:?})"),
}
}
}
impl UInt {
pub fn gen_bin_disp(&self) -> String {
if self.value.is_none() {
return String::from("None");
}
let bytes = self.value.as_ref().unwrap();
if bytes.iter().all(|&b| b == 0) {
return String::from("0");
}
let str = bytes
.iter()
.map(|byte| format!("{:08b}", byte))
.collect::<String>();
str
}
pub fn gen_disp(&self) -> String {
if self.value.is_none() {
return String::from("None");
}
let bytes = self.value.as_ref().unwrap();
if bytes.iter().all(|&b| b == 0) {
return String::from("0");
}
let mut result = Vec::new();
let mut temp = bytes.clone();
while !temp.is_empty() && !temp.iter().all(|&b| b == 0) {
let mut remainder = 0u16;
let mut new_temp = Vec::new();
let mut first = true;
for &byte in &temp {
let current = (remainder << 8) | u16::from(byte);
let quotient = current / 10;
remainder = current % 10;
if !first || quotient != 0 {
new_temp.push(quotient as u8);
first = false;
}
}
result.push(char::from_digit(remainder as u32, 10).unwrap());
temp = new_temp;
}
result.reverse();
result.iter().collect::<String>()
}
pub fn disp(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.gen_disp())
}
pub fn bin_disp(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.gen_bin_disp())
}
}
impl UInt {
pub fn from_str_radix(src: &str, radix: u32) -> Result<Self, IntError> {
if 2 > radix || radix > 36 {
return Err(IntError::ParseErr(ParseErrKind::InvalidRadix));
}
if src.is_empty() {
return Err(IntError::ParseErr(ParseErrKind::Empty));
}
let mut result = UInt::zero(64);
let base = UInt::new(radix as u128);
for c in src.chars() {
let digit = match c.to_digit(radix) {
Some(d) => d as u128,
None => return Err(IntError::ParseErr(ParseErrKind::InvalidDigit)),
};
result = result * base.clone() + UInt::new(digit);
}
Ok(result)
}
pub fn from_hex(src: &str) -> Result<Self, IntError> {
Self::from_str_radix(src, 16)
}
pub fn from_binary(src: &str) -> Result<Self, IntError> {
Self::from_str_radix(src, 2)
}
}
impl Display for UInt {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.dbg_disp_enabled {
Self::bin_disp(self, f)
} else {
Self::disp(self, f)
}
}
}
impl PartialEq for UInt {
fn eq(&self, other: &Self) -> bool {
self.prec == other.prec && self.value.eq(&other.value)
}
}
impl Eq for UInt {}
impl PartialOrd for UInt {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
if self.value.is_none() || other.value.is_none() {
return None;
}
let self_val = self.value.as_ref().unwrap();
let other_val = other.value.as_ref().unwrap();
Some(Self::compare_bytes(self_val, other_val))
}
}
impl Ord for UInt {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.partial_cmp(other).unwrap_or(std::cmp::Ordering::Equal)
}
}
impl Step for UInt {
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
if start > end {
return (0, None);
}
if start.value.is_none() || end.value.is_none() {
return (usize::MAX, None);
}
let mut diff = end.clone();
diff = diff - start.clone();
let bytes = diff.value.unwrap();
let mut result: usize = 0;
for &byte in bytes.iter() {
if result > (usize::MAX - byte as usize) / 256 {
return (usize::MAX, None);
}
result = result * 256 + byte as usize;
}
(result, Some(result))
}
fn forward_checked(start: Self, count: usize) -> Option<Self> {
let increment = Self::from(count as u128);
let result = start.clone() + increment;
Some(result)
}
fn backward_checked(start: Self, count: usize) -> Option<Self> {
let decrement = Self::from(count as u128);
let result = start.clone() - decrement;
if result.value.is_none() {
return None;
}
Some(result)
}
}
impl FromIterator<u8> for UInt {
fn from_iter<I: IntoIterator<Item = u8>>(iter: I) -> Self {
let bytes: Vec<u8> = iter.into_iter().collect();
Self::from_vec(bytes.len() as u64 * 8, Some(bytes)).unwrap_or_default()
}
}
impl From<u8> for UInt {
fn from(value: u8) -> Self {
Self::new(value)
}
}
impl From<u16> for UInt {
fn from(value: u16) -> Self {
Self::new(value)
}
}
impl From<u32> for UInt {
fn from(value: u32) -> Self {
Self::new(value)
}
}
impl From<u64> for UInt {
fn from(value: u64) -> Self {
Self::new(value)
}
}
impl From<u128> for UInt {
fn from(value: u128) -> Self {
Self::new(value)
}
}
impl From<i8> for UInt {
fn from(value: i8) -> Self {
Self::new(value.abs() as u8)
}
}
impl From<i16> for UInt {
fn from(value: i16) -> Self {
Self::new(value.abs() as u16)
}
}
impl From<i32> for UInt {
fn from(value: i32) -> Self {
Self::new(value.abs() as u32)
}
}
impl From<i64> for UInt {
fn from(value: i64) -> Self {
Self::new(value.abs() as u64)
}
}
impl From<i128> for UInt {
fn from(value: i128) -> Self {
Self::new(value.abs() as u128)
}
}
impl TryFrom<UInt> for u128 {
type Error = IntError;
fn try_from(value: UInt) -> Result<Self, Self::Error> {
if value.prec > 128 {
return Err(IntError::Overflow);
}
if value.value.is_none() {
return Err(IntError::NoneVal);
}
let bytes = value.value.unwrap();
let mut result: u128 = 0;
for &byte in bytes.iter() {
result = result.checked_mul(256).ok_or_else(|| IntError::Overflow)?;
result = result
.checked_add(byte as u128)
.ok_or_else(|| IntError::Overflow)?;
}
Ok(result)
}
}
impl TryFrom<UInt> for u64 {
type Error = IntError;
fn try_from(value: UInt) -> Result<Self, Self::Error> {
let value_u128: u128 = value.try_into()?;
value_u128.try_into().map_err(|_| IntError::Overflow)
}
}
impl TryFrom<UInt> for u32 {
type Error = IntError;
fn try_from(value: UInt) -> Result<Self, Self::Error> {
let value_u128: u128 = value.try_into()?;
value_u128.try_into().map_err(|_| IntError::Overflow)
}
}
impl TryFrom<UInt> for u16 {
type Error = IntError;
fn try_from(value: UInt) -> Result<Self, Self::Error> {
let value_u128: u128 = value.try_into()?;
value_u128.try_into().map_err(|_| IntError::Overflow)
}
}
impl TryFrom<UInt> for u8 {
type Error = IntError;
fn try_from(value: UInt) -> Result<Self, Self::Error> {
let value_u128: u128 = value.try_into()?;
value_u128.try_into().map_err(|_| IntError::Overflow)
}
}
impl std::str::FromStr for UInt {
type Err = IntError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let radix =
helpers::detect_radix(s).ok_or(IntError::ParseErr(ParseErrKind::InvalidRadix))?;
Self::from_str_radix(s, radix)
}
}
impl Into<String> for UInt {
fn into(self) -> String {
self.to_string()
}
}
impl std::fmt::Binary for UInt {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.gen_bin_disp())
}
}
impl std::fmt::Octal for UInt {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
if let Some(bytes) = &self.value {
let mut num = 0u128;
for &byte in bytes {
num = num * 256 + byte as u128;
}
write!(f, "{:o}", num)
} else {
write!(f, "None")
}
}
}
impl std::fmt::LowerHex for UInt {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
if let Some(bytes) = &self.value {
for &byte in bytes {
write!(f, "{:02x}", byte)?;
}
Ok(())
} else {
write!(f, "None")
}
}
}
impl std::fmt::UpperHex for UInt {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
if let Some(bytes) = &self.value {
for &byte in bytes {
write!(f, "{:02X}", byte)?;
}
Ok(())
} else {
write!(f, "None")
}
}
}
impl std::hash::Hash for UInt {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.prec.hash(state);
self.value.hash(state);
}
}
impl Sum for UInt {
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::zero(64), |acc, x| acc + x)
}
}
impl Product for UInt {
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::one(64), |acc, x| acc * x)
}
}
pub mod random {
use std::collections::HashSet;
pub struct LCG {
state: u64,
}
impl LCG {
pub fn new(seed: u64) -> Self {
Self { state: seed }
}
pub fn next_u64(&mut self) -> u64 {
const A: u64 = 6364136223846793005;
const C: u64 = 1442695040888963407;
self.state = self.state.wrapping_mul(A).wrapping_add(C);
self.state
}
pub fn next_u32(&mut self) -> u32 {
(self.next_u64() & 0xFFFFFFFF) as u32
}
pub fn next_u16(&mut self) -> u16 {
(self.next_u64() & 0xFFFF) as u16
}
pub fn next_u8(&mut self) -> u8 {
(self.next_u64() & 0xFF) as u8
}
pub fn next_float(&mut self) -> f64 {
const SCALE: f64 = 1.0 / (u64::MAX as f64);
self.next_u64() as f64 * SCALE
}
pub fn next_bool(&mut self) -> bool {
(self.next_u64() & 1) == 1
}
pub fn next_u8_in_range(&mut self, min: u8, max: u8) -> u8 {
assert!(min <= max, "min must not exceed max");
let range = (max - min) as u64 + 1;
min + ((self.next_u64() % range) as u8)
}
pub fn next_u32_in_range(&mut self, min: u32, max: u32) -> u32 {
assert!(min <= max, "min must not exceed max");
let range = (max - min) as u64 + 1;
min + ((self.next_u64() % range) as u32)
}
pub fn next_float_in_range(&mut self, min: f64, max: f64) -> f64 {
assert!(min <= max, "min must not exceed max");
min + (self.next_float() * (max - min))
}
pub fn next_u16_in_range(&mut self, min: u16, max: u16) -> u16 {
assert!(min <= max, "min must not exceed max");
let range = (max - min) as u64 + 1;
min + ((self.next_u64() % range) as u16)
}
pub fn next_ascii_alphabetic(&mut self) -> char {
let base = if self.next_bool() { b'A' } else { b'a' };
(base + (self.next_u8() % 26)) as char
}
pub fn shuffle<T>(&mut self, slice: &mut [T]) {
for i in (1..slice.len()).rev() {
let j = self.next_u32_in_range(0, i as u32) as usize;
slice.swap(i, j);
}
}
pub fn choose<'a, T>(&mut self, slice: &'a [T]) -> Option<&'a T> {
if slice.is_empty() {
None
} else {
Some(&slice[self.next_u32_in_range(0, (slice.len() - 1) as u32) as usize])
}
}
pub fn next_normal(&mut self, mean: f64, std_dev: f64) -> f64 {
let u1 = self.next_float();
let u2 = self.next_float();
let z = (-2.0 * u1.ln()).sqrt() * (2.0 * std::f64::consts::PI * u2).cos();
mean + std_dev * z
}
pub fn next_exponential(&mut self, lambda: f64) -> f64 {
-self.next_float().ln() / lambda
}
pub fn generate_string(&mut self, length: usize) -> String {
(0..length).map(|_| self.next_ascii_alphabetic()).collect()
}
pub fn generate_string_from_charset(&mut self, length: usize, charset: &[char]) -> String {
if charset.is_empty() {
return String::new();
}
(0..length)
.map(|_| {
let idx = self.next_u32_in_range(0, (charset.len() - 1) as u32) as usize;
charset[idx]
})
.collect()
}
pub fn generate_hex_string(&mut self, length: usize) -> String {
const HEX_CHARS: &[char] = &[
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
];
self.generate_string_from_charset(length, HEX_CHARS)
}
pub fn next_poisson(&mut self, lambda: f64) -> u32 {
let l = (-lambda).exp();
let mut k = 0;
let mut p = 1.0;
while p > l {
k += 1;
p *= self.next_float();
}
k - 1
}
pub fn next_bernoulli(&mut self, p: f64) -> bool {
assert!(
(0.0..=1.0).contains(&p),
"probability must be between 0 and 1"
);
self.next_float() < p
}
pub fn next_geometric(&mut self, p: f64) -> u32 {
assert!(
(0.0..=1.0).contains(&p),
"probability must be between 0 and 1"
);
(self.next_float().ln() / (1.0 - p).ln()).ceil() as u32
}
pub fn unique_numbers_in_range(&mut self, min: u32, max: u32, k: u32) -> HashSet<u32> {
assert!(min <= max, "min must not exceed max");
assert!(
k <= max - min + 1,
"cannot generate more unique numbers than range size"
);
let mut result = HashSet::with_capacity(k as usize);
while result.len() < k as usize {
result.insert(self.next_u32_in_range(min, max));
}
result
}
pub fn weighted_choice<'a, T>(&mut self, items: &'a [T], weights: &[f64]) -> Option<&'a T> {
if items.is_empty() || items.len() != weights.len() {
return None;
}
let total: f64 = weights.iter().sum();
let mut value = self.next_float() * total;
for (item, &weight) in items.iter().zip(weights.iter()) {
value -= weight;
if value <= 0.0 {
return Some(item);
}
}
Some(&items[items.len() - 1])
}
pub fn fill_bytes(&mut self, dest: &mut [u8]) {
for chunk in dest.chunks_mut(8) {
let rand_val = self.next_u64();
for (i, byte) in chunk.iter_mut().enumerate() {
*byte = ((rand_val >> (i * 8)) & 0xFF) as u8;
}
}
}
pub fn next_ipv4(&mut self) -> String {
format!(
"{}.{}.{}.{}",
self.next_u8(),
self.next_u8(),
self.next_u8(),
self.next_u8()
)
}
pub fn generate_password(
&mut self,
length: usize,
include_uppercase: bool,
include_numbers: bool,
include_symbols: bool,
) -> String {
const LOWERCASE: &[char] = &[
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
];
const UPPERCASE: &[char] = &[
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
];
const NUMBERS: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
const SYMBOLS: &[char] = &[
'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+',
];
let mut charset = Vec::from(LOWERCASE);
if include_uppercase {
charset.extend_from_slice(UPPERCASE);
}
if include_numbers {
charset.extend_from_slice(NUMBERS);
}
if include_symbols {
charset.extend_from_slice(SYMBOLS);
}
self.generate_string_from_charset(length, &charset)
}
}
impl Default for LCG {
fn default() -> Self {
use std::time::{SystemTime, UNIX_EPOCH};
let seed = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos() as u64;
Self::new(seed)
}
}
}