From 4412b1bc3c7ed3e6058a2df83e83708f078c02df Mon Sep 17 00:00:00 2001 From: Ori Ziv Date: Sun, 1 Sep 2024 16:15:50 +0300 Subject: [PATCH] Added TryInto::. --- corelib/src/circuit.cairo | 95 ++++++++++++++++++++++++++--- corelib/src/test/circuit_test.cairo | 28 +++++++++ 2 files changed, 116 insertions(+), 7 deletions(-) diff --git a/corelib/src/circuit.cairo b/corelib/src/circuit.cairo index aac7586d5bd..a977784a774 100644 --- a/corelib/src/circuit.cairo +++ b/corelib/src/circuit.cairo @@ -431,14 +431,21 @@ mod conversions { use crate::internal::{ bounded_int, bounded_int::{BoundedInt, AddHelper, MulHelper, DivRemHelper} }; + use crate::integer::upcast; + + use super::{u384, u96}; type ConstValue = BoundedInt; + const POW128: felt252 = 0x100000000000000000000000000000000; const POW96: felt252 = 0x1000000000000000000000000; + const POW96_TYPED: ConstValue = 0x1000000000000000000000000; const NZ_POW96_TYPED: NonZero> = 0x1000000000000000000000000; const POW64: felt252 = 0x10000000000000000; + const POW64_TYPED: ConstValue = 0x10000000000000000; const NZ_POW64_TYPED: NonZero> = 0x10000000000000000; const POW32: felt252 = 0x100000000; const POW32_TYPED: ConstValue = 0x100000000; + const NZ_POW32_TYPED: NonZero> = 0x100000000; impl DivRemU128By96 of DivRemHelper> { type DivT = BoundedInt<0, { POW32 - 1 }>; @@ -450,26 +457,88 @@ mod conversions { type RemT = BoundedInt<0, { POW64 - 1 }>; } - impl MulHelperImpl of MulHelper, ConstValue> { + impl DivRemU96By32 of DivRemHelper> { + type DivT = BoundedInt<0, { POW64 - 1 }>; + type RemT = BoundedInt<0, { POW32 - 1 }>; + } + + impl DivRemU96By64 of DivRemHelper> { + type DivT = BoundedInt<0, { POW32 - 1 }>; + type RemT = BoundedInt<0, { POW64 - 1 }>; + } + + impl MulHelper64By32Impl of MulHelper, ConstValue> { type Result = BoundedInt<0, { POW96 - POW32 }>; } - impl AddHelperImpl of AddHelper< + impl MulHelper32By96Impl of MulHelper, ConstValue> { + type Result = BoundedInt<0, { POW128 - POW96 }>; + } + + impl MulHelper64By64Impl of MulHelper, ConstValue> { + type Result = BoundedInt<0, { POW128 - POW64 }>; + } + + impl AddHelperTo96By32Impl of AddHelper< BoundedInt<0, { POW96 - POW32 }>, BoundedInt<0, { POW32 - 1 }> > { - type Result = BoundedInt<0, { POW96 - 1 }>; + type Result = u96; } - pub fn from_u128(value: u128) -> super::u384 { + impl AddHelperTo128By64Impl of AddHelper< + BoundedInt<0, { POW128 - POW64 }>, BoundedInt<0, { POW64 - 1 }> + > { + type Result = BoundedInt<0, { POW128 - 1 }>; + } + + impl AddHelperTo128By96Impl of AddHelper, u96> { + type Result = BoundedInt<0, { POW128 - 1 }>; + } + + pub fn from_u128(value: u128) -> u384 { let (limb1, limb0) = bounded_int::div_rem(value, NZ_POW96_TYPED); - crate::circuit::u384 { limb0, limb1: crate::integer::upcast(limb1), limb2: 0, limb3: 0 } + u384 { limb0, limb1: upcast(limb1), limb2: 0, limb3: 0 } } - pub fn from_u256(value: u256) -> super::u384 { + pub fn from_u256(value: u256) -> u384 { let (limb1_low32, limb0) = bounded_int::div_rem(value.low, NZ_POW96_TYPED); let (limb2, limb1_high64) = bounded_int::div_rem(value.high, NZ_POW64_TYPED); let limb1 = bounded_int::add(bounded_int::mul(limb1_high64, POW32_TYPED), limb1_low32); - crate::circuit::u384 { limb0, limb1, limb2: crate::integer::upcast(limb2), limb3: 0 } + u384 { limb0, limb1, limb2: upcast(limb2), limb3: 0 } + } + + pub fn try_into_u128(value: u384) -> Option { + if value.limb2 != 0 || value.limb3 != 0 { + return Option::None; + } + let (limb1_high, limb1_low) = bounded_int::div_rem(value.limb1, NZ_POW32_TYPED); + if limb1_high != 0 { + return Option::None; + } + Option::Some( + upcast(bounded_int::add(bounded_int::mul(limb1_low, POW96_TYPED), value.limb0)) + ) + } + + pub fn try_into_u256(value: u384) -> Option { + if value.limb3 != 0 { + return Option::None; + } + let (limb2_high, limb2_low) = bounded_int::div_rem(value.limb2, NZ_POW64_TYPED); + if limb2_high != 0 { + return Option::None; + } + let (limb1_high, limb1_low) = bounded_int::div_rem(value.limb1, NZ_POW32_TYPED); + Option::Some( + u256 { + high: upcast( + bounded_int::add(bounded_int::mul(limb2_low, POW64_TYPED), limb1_high) + ), + low: upcast( + bounded_int::add(bounded_int::mul(limb1_low, POW96_TYPED), value.limb0) + ), + } + ) } } @@ -490,3 +559,15 @@ impl Felt252IntoU384 of Into { conversions::from_u256(self.into()) } } + +impl U384TryIntoU128 of TryInto { + fn try_into(self: u384) -> Option { + conversions::try_into_u128(self) + } +} + +impl U384TryIntoU256 of TryInto { + fn try_into(self: u384) -> Option { + conversions::try_into_u256(self) + } +} diff --git a/corelib/src/test/circuit_test.cairo b/corelib/src/test/circuit_test.cairo index bda227010a7..aa8d0a79ee1 100644 --- a/corelib/src/test/circuit_test.cairo +++ b/corelib/src/test/circuit_test.cairo @@ -88,6 +88,34 @@ fn test_into_u384() { ); } +#[test] +fn test_from_u384() { + let limb0 = 0xb000000cd000000ef0000000; + let limb1 = 0x50000006700000089000000a; + let limb2 = 0x1000000230000004; + let limb3 = 0; + assert!( + u384 { limb0, limb1, limb2, limb3 } + .try_into() == Option::Some( + 0x100000023000000450000006700000089000000ab000000cd000000ef0000000_u256 + ) + ); + assert!(u384 { limb0, limb1, limb2, limb3: 1 }.try_into() == Option::::None); + assert!( + u384 { limb0, limb1, limb2: 0x11000000230000004, limb3 }.try_into() == Option::::None + ); + let limb0 = 0x300000045000000670000008; + let limb1 = 0x10000002; + let limb2 = 0; + let limb3 = 0; + assert!( + u384 { limb0, limb1, limb2, limb3 } + .try_into() == Option::Some(0x10000002300000045000000670000008_u128) + ); + assert!(u384 { limb0, limb1: 0x110000002, limb2, limb3 }.try_into() == Option::::None); + assert!(u384 { limb0, limb1, limb2: 1, limb3 }.try_into() == Option::::None); + assert!(u384 { limb0, limb1, limb2, limb3: 1 }.try_into() == Option::::None); +} #[test] fn test_fill_inputs_loop() {