diff --git a/builtin/bigint.mbt b/builtin/bigint.mbt index 054990e1c..cd2997df4 100644 --- a/builtin/bigint.mbt +++ b/builtin/bigint.mbt @@ -61,9 +61,9 @@ let karatsuba_threshold = 50 // Useful bigints -let zero : BigInt = 0N +let zero : BigInt = { limbs: [0], sign: Positive, len: 1 } -let one : BigInt = 1N +let one : BigInt = { limbs: [1], sign: Positive, len: 1 } // Conversion Functions @@ -72,10 +72,79 @@ pub fn BigInt::from_int(n : Int) -> BigInt { BigInt::from_int64(n.to_int64()) } +pub fn BigInt::equal_int64(self : BigInt, n : Int64) -> Bool { + // Check if the sign of BigInt matches the sign of n + if (self.sign == Negative && n >= 0) || (self.sign == Positive && n < 0) { + return false + } + + // Handle zero case + if n == 0L { + return self.is_zero() + } + + // Convert n to positive for comparison + let mut m = if n < 0L { -n } else { n } + let mut i = 0 + + // Compare limbs + while m > 0L { + if i >= self.len || self.limbs[i] != (m % radix).to_int() { + return false + } + m /= radix + i += 1 + } + + // Ensure all remaining limbs in BigInt are zero + while i < self.len { + if self.limbs[i] != 0 { + return false + } + i += 1 + } + true +} + +pub fn BigInt::equal_int(self : BigInt, other : Int) -> Bool { + // Check if the sign of BigInt matches the sign of other + if (self.sign == Negative && other >= 0) || + (self.sign == Positive && other < 0) { + return false + } + + // Handle zero case + if other == 0 { + return self.is_zero() + } + + // Convert other to positive for comparison + let mut m = if other < 0 { -other } else { other } + let mut i = 0 + + // Compare limbs + while m > 0 { + if i >= self.len || self.limbs[i] != m % radix.to_int() { + return false + } + m /= radix.to_int() + i += 1 + } + + // Ensure all remaining limbs in BigInt are zero + while i < self.len { + if self.limbs[i] != 0 { + return false + } + i += 1 + } + true +} + /// Convert an Int64 to a BigInt. pub fn BigInt::from_int64(n : Int64) -> BigInt { if n == 0L { - return { limbs: FixedArray::make(1, 0), sign: Positive, len: 1 } + return zero } let limbs = FixedArray::make(64 / radix_bit_len, 0U) let mut m = (if n < 0L { -n } else { n }).to_uint64() diff --git a/builtin/bigint_wbtest.mbt b/builtin/bigint_wbtest.mbt index 7ce5cfd01..40971ed69 100644 --- a/builtin/bigint_wbtest.mbt +++ b/builtin/bigint_wbtest.mbt @@ -20,6 +20,47 @@ impl Show for MyBigInt with output(self, logger) { ) } +test { + inspect!( + MyBigInt(BigInt::from_int64(0)), + content="{limbs : [0], sign : Positive, len : 1 }", + ) + inspect!( + MyBigInt(BigInt::from_int64(1)), + content="{limbs : [1, 0, 0, 0], sign : Positive, len : 1 }", + ) + inspect!(MyBigInt(1), content="{limbs : [1, 0], sign : Positive, len : 1 }") + inspect!( + MyBigInt(0xffff_ffff), + content="{limbs : [65535, 65535, 0, 0], sign : Positive, len : 2 }", + ) + inspect!( + MyBigInt(0xffff_ffff_ffff_ffff), + content="{limbs : [65535, 65535, 65535, 65535, 0, 0], sign : Positive, len : 4 }", + ) +} + +test "equal_int64" { + assert_eq!(BigInt::from_int64(0).equal_int64(0), true) + assert_eq!(BigInt::from_int64(1).equal_int64(1), true) + assert_eq!(BigInt::from_int64(0xffff_ffff).equal_int64(0xffff_ffff), true) + inspect!(BigInt::from_int64(0xffff_ffff_ffff_ffff), content="-1") + inspect!(0xffff_ffff_ffff_ffffN, content="18446744073709551615") + assert_eq!( + BigInt::from_int64(0xffff_ffff_ffff_ffff).equal_int64(0xffff_ffff_ffff_ffff), + true, + ) +} + +test "equal_int" { + assert_eq!(BigInt::from_int64(0).equal_int(0), true) + assert_eq!(BigInt::from_int64(1).equal_int(1), true) + // overflow + assert_eq!(BigInt::from_int64(0xffff_ffff).equal_int(0xffff_ffff), false) + assert_eq!(BigInt::from_int64(0x7fff_ffff).equal_int(0x7fff_ffff), true) + assert_eq!(BigInt::from_int64(0x8fff_ffff).equal_int(0x8fff_ffff), false) +} + test "debug_string" { let buf = Buffer::new() let v : Array[MyBigInt] = [0, 1, 2, 3, 4, -0, -1, -2, -3] diff --git a/builtin/builtin.mbti b/builtin/builtin.mbti index c2b4888f0..93e198b92 100644 --- a/builtin/builtin.mbti +++ b/builtin/builtin.mbti @@ -129,6 +129,8 @@ type BigInt impl BigInt { asr(Self, Int) -> Self compare(Self, Self) -> Int + equal_int(Self, Int) -> Bool + equal_int64(Self, Int64) -> Bool from_hex(String) -> Self from_int(Int) -> Self from_int64(Int64) -> Self