From 6200fec2f29193aadf2cccc3c94361834fbe16d2 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 30 Aug 2022 17:13:15 +0200 Subject: [PATCH] 256 bit integer types. --- Cargo.toml | 8 ++++ src/main.rs | 5 +++ src/u256.rs | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 Cargo.toml create mode 100644 src/main.rs create mode 100644 src/u256.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..97bd4fe --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "pathfinder2" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..c392296 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,5 @@ +mod u256; + +fn main() { + println!("Hello, world!"); +} diff --git a/src/u256.rs b/src/u256.rs new file mode 100644 index 0000000..62bac9d --- /dev/null +++ b/src/u256.rs @@ -0,0 +1,120 @@ +use std::fmt::Display; +use std::fmt::Formatter; +use std::ops::{Add, AddAssign}; + +#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, PartialOrd)] +pub struct U256([u128; 2]); + +impl U256 {} + +impl From for U256 { + fn from(item: u128) -> Self { + U256([0, item]) + } +} + +// TODO str is using unicode stuff - maybe we should use Vec for efficiency reasons? +impl From<&str> for U256 { + fn from(item: &str) -> Self { + if item.starts_with("0x") { + let len = item.len(); + assert!(len <= 2 + 32 + 32, "{}", len); + let low_start = if len >= 2 + 32 { len - 32 } else { 2 }; + let low_hex = &item[low_start..]; + // disallow + and - prefixes + assert!( + low_hex.as_bytes().get(0) != Some(&54) && low_hex.as_bytes().get(0) != Some(&43) + ); + let low = if low_hex.is_empty() { 0 } else {u128::from_str_radix(low_hex, 16).unwrap()}; + let high_start = if len >= 2 + 32 + 32 { len - 64 } else { 2 }; + let high_hex = &item[high_start..low_start]; + // disallow + and - prefixes + assert!( + high_hex.as_bytes().get(0) != Some(&54) && high_hex.as_bytes().get(0) != Some(&43) + ); + let high = if high_hex.is_empty() { 0 } else { u128::from_str_radix(high_hex, 16).unwrap() }; + U256([high, low]) + } else { + todo!("Decimal import"); + } + } +} + +impl Add for U256 { + type Output = Self; + fn add(self, rhs: Self) -> Self { + let (low, carry) = self.0[1].overflowing_add(rhs.0[1]); + let (mut high, mut overflow) = self.0[0].overflowing_add(rhs.0[0]); + assert!(!overflow); + if carry { + (high, overflow) = high.overflowing_add(1); + assert!(!overflow); + } + Self([high, low]) + } +} + +impl AddAssign for U256 { + fn add_assign(&mut self, rhs: U256) { + *self = *self + rhs; + } +} + +impl Display for U256 { + fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { + if self.0[0] == 0 { + write!(f, "{:#x}", self.0[1]) + } else { + write!(f, "{:#x}{:032x}", self.0[0], self.0[1]) + } + } +} + +mod test { + use super::*; + #[test] + fn to_string() { + assert_eq!(format!("{}", U256::from(0)), "0x0"); + assert_eq!( + format!("{}", U256::from(u128::MAX)), + "0xffffffffffffffffffffffffffffffff" + ); + } + + #[test] + fn add() { + assert_eq!( + format!("{}", U256::from(u128::MAX) + U256::from(u128::MAX)), + "0x1fffffffffffffffffffffffffffffffe" + ); + let mut x = U256::from(u128::MAX); + x += U256::from(1); + assert_eq!(format!("{x}"), "0x100000000000000000000000000000000"); + } + + #[test] + fn compare() { + assert!(U256::from(0) < U256::from(1)); + assert!(U256::from("0x100000000000000000000000000000000") > U256::from(1)); + } + + #[test] + fn from_hex() { + assert_eq!(U256::from("0x"), U256::from(0)); + assert_eq!(U256::from("0x1"), U256::from(1)); + assert_eq!(U256::from("0x01"), U256::from(1)); + assert_eq!( + U256::from("0x1fffffffffffffffffffffffffffffffe"), + U256::from(u128::MAX) + U256::from(u128::MAX) + ); + assert_eq!( + U256::from("0x001fffffffffffffffffffffffffffffffe"), + U256::from(u128::MAX) + U256::from(u128::MAX) + ); + assert_eq!( + U256::from("0x100000000000000000000000000000000"), + U256::from(u128::MAX) + U256::from(1) + ); + } + +}