Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hongbo/bigarray equal address #926 #937

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 72 additions & 3 deletions builtin/bigint.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is incorrect after #935

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, 0)
let mut m = if n < 0L { -n } else { n }
Expand Down
41 changes: 41 additions & 0 deletions builtin/bigint_wbtest.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
2 changes: 2 additions & 0 deletions builtin/builtin.mbti
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,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
Expand Down