Skip to content

Commit

Permalink
std::math::big: add the & and &= operator support to the Int structure
Browse files Browse the repository at this point in the history
  • Loading branch information
mertcandav committed Mar 10, 2024
1 parent a1f7689 commit 065cd75
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 14 deletions.
15 changes: 15 additions & 0 deletions std/math/big/bits.jule
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,21 @@ fn or(mut &a: bits, &b: bits) {
}
}

// Bitwise and.
// a's bitsize should be have same or greather than b's bitsize.
fn and(mut &a: bits, &b: bits) {
for i in b {
a[i] &= b[i]
}
// Clean trailing bits.
if a.len > b.len {
let mut trail = a[b.len:]
for i in trail {
trail[i] = 0b0
}
}
}

// Update bits by 1's complement.
fn ones_complement(mut &b: bits) {
for i, x in b {
Expand Down
36 changes: 36 additions & 0 deletions std/math/big/int.jule
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,48 @@ impl Int {
twos_complement(y.nat.bits)
}
or(self.nat.bits, y.nat.bits)
if self.neg && self.len() >= y.len() {
twos_complement(self.nat.bits)
}
if y.neg {
twos_complement(y.nat.bits)
}
self.nat.fit()
}

// Bitwise and.
pub fn bit_and(self, y: Int): Int {
let mut r = self
r &= y
ret r
}

// Bitwise and for assignment.
pub fn bit_and_assign(mut self, y: Int) {
if self.len() < y.len() {
let mut xb = make(bits, y.len())
_ = copy(xb, self.nat.bits)
self.nat.bits = xb
}
if self.neg {
twos_complement(self.nat.bits)
}
if y.neg {
twos_complement(y.nat.bits)
}
if !self.neg && y.neg && self.len() > y.len() {
let mut x = self.nat.bits[:y.len()]
and(x, y.nat.bits)
} else {
and(self.nat.bits, y.nat.bits)
}
if y.neg {
twos_complement(y.nat.bits)
if self.neg {
twos_complement(self.nat.bits)
}
}
self.neg = self.neg && y.neg
self.nat.fit()
}

Expand Down
45 changes: 38 additions & 7 deletions std/math/big/int_test.jule
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,23 @@ static cases_int_bit_or: [][]i64 = [
[-4, 20, -4],
[-345, 2, -345],
[-908474739, 747688553334, -570560513],
[-97799739579632223, 1234567890, -97799738497239053],
]

static cases_int_bit_and: [][]i64 = [
[902984, 24, 8],
[24, 902984, 8],
[902984, 2434, 256],
[2434, 902984, 256],
[77786486463864864, 97774749933, 19360907296],
[123456789, 987654321, 39471121],
[5, -3, 5],
[-5, 3, 3],
[-8884973, 88893, 18705],
[88893, -8884973, 18705],
[13452, -12345, 1156],
[-13452, -12345, -13500],
[-12345, -13452, -13500],
]

fn test_common_int_op(mut &t: &T, op: str, &cases: [][]str) {
Expand Down Expand Up @@ -160,19 +177,33 @@ fn test_int_bit_not(mut t: &T) {
}
}

#test
fn test_int_bit_or(mut t: &T) {
for _, c in cases_int_bit_or {
let n1 = Int.new(c[0])
fn test_int_bit_binary(mut &t: &T, op: str, &cases: [][]i64) {
for _, c in cases {
let mut n1 = Int.new(c[0])
let n2 = Int.new(c[1])
let r = n1 | n2
let i = r.to_i64()!
match op {
| "|":
n1 |= n2
| "&":
n1 &= n2
}
let i = n1.to_i64()!
if i != c[2] {
t.errorf("{} | {} != {}", c[0], c[1], c[2])
t.errorf("{} {} {} != {}", c[0], op, c[1], c[2])
}
}
}

#test
fn test_int_bit_or(mut t: &T) {
test_int_bit_binary(t, "|", cases_int_bit_or)
}

#test
fn test_int_bit_and(mut t: &T) {
test_int_bit_binary(t, "&", cases_int_bit_and)
}

#test
fn test_int_lt(mut t: &T) {
t.assert(!Int.from_bits("1011010", false)!.lt(Int.from_bits("00001011010", false)!), "1) 1011010 < 00001011010")
Expand Down
17 changes: 17 additions & 0 deletions std/math/big/nat.jule
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,23 @@ impl Nat {
or(self.bits, y.bits)
}

// Bitwise and.
pub fn bit_and(self, y: Nat): Nat {
let mut r = self
r &= y
ret r
}

// Bitwise and for assignment.
pub fn bit_and_assign(mut self, y: Nat) {
if self.len() < y.len() {
self = y & self
ret
}
self.bits = clone(self.bits)
and(self.bits, y.bits)
}

// Compares bits.
// Returns +1 if self > y.
// Returns 0 if self == y.
Expand Down
37 changes: 30 additions & 7 deletions std/math/big/nat_test.jule
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,15 @@ static cases_nat_bit_or: [][]u64 = [
[97799739579632223, 1234567890, 97799739731806943],
]

static cases_nat_bit_and: [][]u64 = [
[902984, 24, 8],
[24, 902984, 8],
[902984, 2434, 256],
[2434, 902984, 256],
[77786486463864864, 97774749933, 19360907296],
[123456789, 987654321, 39471121]
]

#test
fn test_nat_from_bits(mut t: &T) {
for _, c in cases_nat_from_bits {
Expand Down Expand Up @@ -189,19 +198,33 @@ fn test_nat_mod(mut t: &T) {
test_common_nat_op(t, "%", cases_nat_mod)
}

#test
fn test_nat_bit_or(mut t: &T) {
for _, c in cases_nat_bit_or {
let n1 = Nat.new(c[0])
fn test_nat_bit_binary(mut &t: &T, op: str, &cases: [][]u64) {
for _, c in cases {
let mut n1 = Nat.new(c[0])
let n2 = Nat.new(c[1])
let r = n1 | n2
let u = r.to_u64()!
match op {
| "|":
n1 |= n2
| "&":
n1 &= n2
}
let u = n1.to_u64()!
if u != c[2] {
t.errorf("{} | {} != {}", c[0], c[1], c[2])
t.errorf("{} {} {} != {}", c[0], op, c[1], c[2])
}
}
}

#test
fn test_nat_bit_or(mut t: &T) {
test_nat_bit_binary(t, "|", cases_nat_bit_or)
}

#test
fn test_nat_bit_and(mut t: &T) {
test_nat_bit_binary(t, "&", cases_nat_bit_and)
}

#test
fn test_nat_shl(mut t: &T) {
for _, c in cases_nat_shl {
Expand Down

0 comments on commit 065cd75

Please sign in to comment.