zenyx-engine-telemetry/engine/src/bint.rs
2025-04-22 21:52:01 +02:00

334 lines
8.4 KiB
Rust

use std::{
cmp::Ordering,
convert::From,
fmt,
hash::{Hash, Hasher},
ops::{
Add, AddAssign, BitAnd, BitOr, BitXor, Deref, DerefMut, Div, DivAssign, Mul, MulAssign,
Rem, RemAssign, Shl, Shr, Sub, SubAssign,
},
str::FromStr,
};
#[derive(Debug, Clone, Copy)]
pub struct BigInt<const N: usize> {
bytes: [u8; N],
len: usize,
}
impl<const N: usize> BigInt<N> {
pub fn from_bytes(bytes: &[u8]) -> Self {
debug_assert!(bytes.len() != 0);
let mut len = bytes.len();
while len > 1 && bytes[len - 1] == 0 {
len -= 1;
}
let mut arr = [0u8; N];
arr[..len].copy_from_slice(&bytes[..len]);
BigInt { bytes: arr, len }
}
pub fn from_u64(value: u64) -> Self {
Self::from_bytes(&value.to_le_bytes())
}
fn trim_zeros(mut self) -> Self {
while self.len > 1 && self.bytes[self.len - 1] == 0 {
self.len -= 1;
}
self
}
pub fn max_value() -> Self {
let mut arr = [0u8; N];
arr.fill(255);
BigInt { bytes: arr, len: N }
}
pub fn div_rem(&self, other: &Self) -> (Self, Self) {
let mut quotient = BigInt::from(0);
let mut remainder = self.clone();
let divisor = other.clone();
while remainder >= divisor {
let mut multiple = divisor.clone();
let mut temp_quotient = BigInt::from(1);
while multiple + multiple <= remainder {
multiple = multiple + multiple;
temp_quotient = temp_quotient + temp_quotient;
}
remainder = remainder - multiple;
quotient = quotient + temp_quotient;
}
(quotient.trim_zeros(), remainder.trim_zeros())
}
}
impl<const N: usize> Add for BigInt<N> {
type Output = Self;
fn add(self, rhs: Self) -> Self {
let mut result = [0u8; N];
let mut carry = 0u16;
let max_len = self.len.max(rhs.len);
let mut res_len = 0;
for i in 0..max_len {
let a = self.bytes.get(i).copied().unwrap_or(0) as u16;
let b = rhs.bytes.get(i).copied().unwrap_or(0) as u16;
let sum = a + b + carry;
result[i] = (sum % 256) as u8;
carry = sum / 256;
res_len = i + 1;
}
if carry > 0 {
result[res_len] = carry as u8;
res_len += 1;
}
BigInt {
bytes: result,
len: res_len,
}
.trim_zeros()
}
}
impl<const N: usize> AddAssign for BigInt<N> {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
impl<const N: usize> Sub for BigInt<N> {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
let mut result = [0u8; N];
let mut borrow = 0i16;
let mut res_len = 0;
for i in 0..self.len {
let a = self.bytes[i] as i16;
let b = rhs.bytes.get(i).copied().unwrap_or(0) as i16;
let mut diff = a - b - borrow;
borrow = 0;
if diff < 0 {
diff += 256;
borrow = 1;
}
result[i] = diff as u8;
res_len = i + 1;
}
BigInt {
bytes: result,
len: res_len,
}
.trim_zeros()
}
}
impl<const N: usize> SubAssign for BigInt<N> {
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
impl<const N: usize> Mul for BigInt<N> {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
let mut result = BigInt {
bytes: [0; N],
len: 0,
};
for i in 0..self.len {
let mut carry = 0u16;
for j in 0..rhs.len {
let idx = i + j;
if idx >= N {
panic!("Multiplication overflow");
}
let product =
self.bytes[i] as u16 * rhs.bytes[j] as u16 + carry + result.bytes[idx] as u16;
result.bytes[idx] = (product % 256) as u8;
carry = product / 256;
}
let mut k = i + rhs.len;
while carry > 0 && k < N {
let sum = result.bytes[k] as u16 + carry;
result.bytes[k] = (sum % 256) as u8;
carry = sum / 256;
k += 1;
}
result.len = result.len.max(k);
}
result.trim_zeros()
}
}
impl<const N: usize> MulAssign for BigInt<N> {
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
impl<const N: usize> Div for BigInt<N> {
type Output = Self;
fn div(self, rhs: Self) -> Self {
self.div_rem(&rhs).0
}
}
impl<const N: usize> DivAssign for BigInt<N> {
fn div_assign(&mut self, rhs: Self) {
*self = *self / rhs;
}
}
impl<const N: usize> Rem for BigInt<N> {
type Output = Self;
fn rem(self, rhs: Self) -> Self {
self.div_rem(&rhs).1
}
}
impl<const N: usize> RemAssign for BigInt<N> {
fn rem_assign(&mut self, rhs: Self) {
*self = *self % rhs;
}
}
impl<const N: usize> PartialEq for BigInt<N> {
fn eq(&self, other: &Self) -> bool {
self.bytes[..self.len] == other.bytes[..other.len]
}
}
impl<const N: usize> Eq for BigInt<N> {}
impl<const N: usize> Hash for BigInt<N> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.bytes[..self.len].hash(state);
}
}
impl<const N: usize> PartialOrd for BigInt<N> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<const N: usize> Ord for BigInt<N> {
fn cmp(&self, other: &Self) -> Ordering {
if self.len != other.len {
return self.len.cmp(&other.len);
}
for i in (0..self.len).rev() {
match self.bytes[i].cmp(&other.bytes[i]) {
Ordering::Equal => continue,
ord => return ord,
}
}
Ordering::Equal
}
}
impl<const N: usize> Deref for BigInt<N> {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.bytes[..self.len]
}
}
impl<const N: usize> DerefMut for BigInt<N> {
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.bytes[..self.len]
}
}
macro_rules! impl_from_int {
($($t:ty),*) => {$(
impl<const N: usize> From<$t> for BigInt<N> {
fn from(value: $t) -> Self {
let bytes = value.to_le_bytes();
Self::from_bytes(&bytes)
}
}
)*};
}
impl_from_int!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128);
impl<const N: usize> FromStr for BigInt<N> {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut result = BigInt::from(0u8);
for c in s.chars() {
if !c.is_digit(10) {
return Err("Invalid digit");
}
let digit = c.to_digit(10).unwrap() as u8;
result = result * BigInt::from(10u8) + BigInt::from(digit);
}
Ok(result)
}
}
impl<const N: usize> fmt::Display for BigInt<N> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.len == 0 {
return write!(f, "0");
}
let mut digits = Vec::new();
let mut bytes = self.bytes[..self.len].to_vec();
while !bytes.is_empty() {
let mut remainder = 0u16;
for byte in bytes.iter_mut().rev() {
let value = *byte as u16 + remainder * 256;
*byte = (value / 10) as u8;
remainder = value % 10;
}
digits.push(remainder as u8);
while !bytes.is_empty() && bytes[bytes.len() - 1] == 0 {
bytes.pop();
}
}
digits.reverse();
let s = digits
.iter()
.map(|d| char::from_digit(*d as u32, 10).unwrap())
.collect::<String>();
write!(f, "{}", s)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
struct Dint {
bytes: Vec<u8>,
}
impl Deref for Dint {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.bytes
}
}
impl DerefMut for Dint {
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.bytes
}
}
pub fn main() {
type TheInt = BigInt<2>;
let mut test: TheInt = TheInt::max_value();
let thing = BigInt::<9>::max_value();
test /= 2.into();
println!("{test}")
}