Skip to content

Commit

Permalink
feat: change packed 256 struct to just use u256
Browse files Browse the repository at this point in the history
  • Loading branch information
JhChoy committed Jun 19, 2024
1 parent b296041 commit 86b8de9
Showing 1 changed file with 52 additions and 85 deletions.
137 changes: 52 additions & 85 deletions src/libraries/packed_u256.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -3,93 +3,68 @@ use starknet::storage_access::{StorePacking};
const TWO_POW_64: u256 = 0x10000000000000000; // 2**64
const MASK_64: u256 = 0xFFFFFFFFFFFFFFFF; // 2**64 - 1

#[derive(Copy, Drop, Serde, Debug)]
pub struct PackedU256 {
pub data: u256
pub fn get_u64(packed: u256, n: u8) -> u64 {
assert(n < 4, 'Index out of bounds');
let mut _packed = packed;
let mut index = n;
while index > 0 {
_packed /= TWO_POW_64;
index -= 1;
};
(_packed & MASK_64).try_into().unwrap()
}

#[generate_trait]
impl PackedU256Impl of PackedU256Trait {
fn get_u64(self: PackedU256, n: u8) -> u64 {
assert(n < 4, 'Index out of bounds');
let mut value = self.data;
let mut index = n;
while index > 0 {
value /= TWO_POW_64;
index -= 1;
};
(value & MASK_64).try_into().unwrap()
}

fn update_64(self: PackedU256, n: u8, value: u64) -> PackedU256 {
assert(n < 4, 'Index out of bounds');
let mut packed = self.data;
let mut data: u256 = value.into();
let mut mask: u256 = MASK_64;
let mut index = n;
while index > 0 {
data *= TWO_POW_64;
mask *= TWO_POW_64;
index -= 1;
};
PackedU256 { data: (packed & ~mask) + data }
}

fn sub_u64(self: PackedU256, n: u8, value: u64) -> PackedU256 {
assert(n < 4, 'Index out of bounds');
self.update_64(n, self.get_u64(n) - value)
}
pub fn update_64(packed: u256, n: u8, value: u64) -> u256 {
assert(n < 4, 'Index out of bounds');
let mut _packed = packed;
let mut data: u256 = value.into();
let mut mask: u256 = MASK_64;
let mut index = n;
while index > 0 {
data *= TWO_POW_64;
mask *= TWO_POW_64;
index -= 1;
};
(packed & ~mask) + data
}

impl PackedU256StoragePacking of StorePacking<PackedU256, u256> {
fn pack(value: PackedU256) -> u256 {
value.data
}

fn unpack(value: u256) -> PackedU256 {
PackedU256 { data: value }
}
pub fn sub_u64(packed: u256, n: u8, value: u64) -> u256 {
assert(n < 4, 'Index out of bounds');
update_64(packed, n, get_u64(packed, n) - value)
}

#[cfg(test)]
mod tests {
use super::PackedU256;
use super::PackedU256Trait;
use super::{get_u64, update_64, sub_u64};

#[test]
fn get_u64() {
let packed = PackedU256 {
data: 0x4444444444444444333333333333333322222222222222221111111111111111
};
assert_eq!(packed.get_u64(0), 0x1111111111111111);
assert_eq!(packed.get_u64(1), 0x2222222222222222);
assert_eq!(packed.get_u64(2), 0x3333333333333333);
assert_eq!(packed.get_u64(3), 0x4444444444444444);
fn test_get_u64() {
let packed: u256 = 0x4444444444444444333333333333333322222222222222221111111111111111;
assert_eq!(get_u64(packed, 0), 0x1111111111111111);
assert_eq!(get_u64(packed, 1), 0x2222222222222222);
assert_eq!(get_u64(packed, 2), 0x3333333333333333);
assert_eq!(get_u64(packed, 3), 0x4444444444444444);
}

#[test]
#[should_panic(expected: ('Index out of bounds',))]
fn get_u64_out_of_bounds() {
let packed = PackedU256 {
data: 0x4444444444444444333333333333333322222222222222221111111111111111
};
packed.get_u64(4);
fn test_get_u64_out_of_bounds() {
let packed = 0x4444444444444444333333333333333322222222222222221111111111111111;
get_u64(packed, 4);
}

#[test]
fn update_64() {
let packed = PackedU256 {
data: 0x4444444444444444333333333333333322222222222222221111111111111111
};
fn test_update_64() {
let packed = 0x4444444444444444333333333333333322222222222222221111111111111111;
let mut i = 0;
while (i < 4) {
let updated = packed.update_64(i, 0x123456789ABCDEF0);
let updated = update_64(packed, i, 0x123456789ABCDEF0);
let mut j = 0;
while (j < 4) {
if (j == i) {
assert_eq!(updated.get_u64(j), 0x123456789ABCDEF0);
assert_eq!(get_u64(updated, j), 0x123456789ABCDEF0);
} else {
assert_eq!(updated.get_u64(j), packed.get_u64(j));
assert_eq!(get_u64(updated, j), get_u64(packed, j));
}
j += 1;
};
Expand All @@ -99,28 +74,24 @@ mod tests {

#[test]
#[should_panic(expected: ('Index out of bounds',))]
fn update_64_out_of_bounds() {
let packed = PackedU256 {
data: 0x4444444444444444333333333333333322222222222222221111111111111111
};
packed.update_64(4, 0x123456789ABCDEF0);
fn test_update_64_out_of_bounds() {
let packed = 0x4444444444444444333333333333333322222222222222221111111111111111;
update_64(packed, 4, 0x123456789ABCDEF0);
}

#[test]
fn sub_u64() {
let packed = PackedU256 {
data: 0x4444444444444444333333333333333322222222222222221111111111111111
};
fn test_sub_u64() {
let packed = 0x4444444444444444333333333333333322222222222222221111111111111111;
let base_hex = 0x1111111111111111;
let mut i = 0;
while (i < 4) {
let updated = packed.sub_u64(i, base_hex * i.into());
let updated = sub_u64(packed, i, base_hex * i.into());
let mut j = 0;
while (j < 4) {
if (j == i) {
assert_eq!(updated.get_u64(j), base_hex);
assert_eq!(get_u64(updated, j), base_hex);
} else {
assert_eq!(updated.get_u64(j), packed.get_u64(j));
assert_eq!(get_u64(updated, j), get_u64(packed, j));
}
j += 1;
};
Expand All @@ -130,19 +101,15 @@ mod tests {

#[test]
#[should_panic(expected: ('Index out of bounds',))]
fn sub_u64_out_of_bounds() {
let packed = PackedU256 {
data: 0x4444444444444444333333333333333322222222222222221111111111111111
};
packed.sub_u64(4, 0x1111111111111111);
fn test_sub_u64_out_of_bounds() {
let packed = 0x4444444444444444333333333333333322222222222222221111111111111111;
sub_u64(packed, 4, 0x1111111111111111);
}

#[test]
#[should_panic(expected: ('u64_sub Overflow',))]
fn sub_u64_overflow() {
let packed = PackedU256 {
data: 0x4444444444444444333333333333333322222222222222221111111111111111
};
packed.sub_u64(0, 0x1111111111111112);
let packed = 0x4444444444444444333333333333333322222222222222221111111111111111;
sub_u64(packed, 0, 0x1111111111111112);
}
}

0 comments on commit 86b8de9

Please sign in to comment.