Skip to content

Commit

Permalink
rewrite bitwise operations to infix style (#999)
Browse files Browse the repository at this point in the history
* format bitwise operations to infix style

* fix dead loop

* format code
  • Loading branch information
Yoorkin authored Sep 14, 2024
1 parent 9581e32 commit fe49546
Show file tree
Hide file tree
Showing 26 changed files with 511 additions and 550 deletions.
62 changes: 30 additions & 32 deletions builtin/bigint.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,8 @@ fn karatsuba_mul(self : BigInt, other : BigInt) -> BigInt {
let p1 = xh * yh
let p2 = xl * yl
let p3 = (xh + xl) * (yh + yl)
p1.shl(radix_bit_len * 2 * half) +
(p3 - p1 - p2).shl(radix_bit_len * half) +
(p1 << (radix_bit_len * 2 * half)) +
((p3 - p1 - p2) << (radix_bit_len * half)) +
p2
}

Expand Down Expand Up @@ -328,8 +328,8 @@ fn grade_school_div(self : BigInt, other : BigInt) -> (BigInt, BigInt) {
(64 - divisor.limbs[divisor.len - 1].to_uint64().to_int64().clz()),
)
let a_len = dividend.len
let dividend = dividend.shl(lshift)
let divisor = divisor.shl(lshift)
let dividend = dividend << lshift
let divisor = divisor << lshift
let b_len = divisor.len
let b = FixedArray::make(b_len, 0UL)
for i = 0; i < b_len; i = i + 1 {
Expand Down Expand Up @@ -370,24 +370,24 @@ fn grade_school_div(self : BigInt, other : BigInt) -> (BigInt, BigInt) {
borrow += a[i + j].to_int64()
borrow -= carry.land(radix_mask).to_int64()
a[i + j] = borrow.land(radix_mask.to_int64()).to_uint64()
borrow = borrow.shr(radix_bit_len)
borrow = borrow >> radix_bit_len
carry = carry.lsr(radix_bit_len)
}
borrow = borrow + a[i + b_len].to_int64()
borrow -= carry.to_int64()
a[i + b_len] = borrow.land(radix_mask.to_int64()).to_uint64()
borrow = borrow.shr(radix_bit_len)
borrow = borrow >> radix_bit_len
if borrow < 0L {
carry = 0UL
for j = 0; j < b_len; j = j + 1 {
carry += a[i + j]
carry += b[j]
a[i + j] = carry.land(radix_mask)
carry = carry.shr(radix_bit_len)
a[i + j] = carry & radix_mask
carry = carry >> radix_bit_len
}
carry += a[i + b_len]
a[i + b_len] = carry.land(radix_mask)
carry = carry.shr(radix_bit_len)
a[i + b_len] = carry & radix_mask
carry = carry >> radix_bit_len
borrow += carry.to_int64()
qh -= 1
}
Expand All @@ -410,7 +410,7 @@ fn grade_school_div(self : BigInt, other : BigInt) -> (BigInt, BigInt) {
modulo[j] = a[j].to_uint()
}
let modulo = { limbs: modulo, sign: Positive, len: i }
({ limbs: q, sign: Positive, len }, modulo.shr(lshift))
({ limbs: q, sign: Positive, len }, modulo >> lshift)
}

// Bitwise Operations
Expand All @@ -433,7 +433,7 @@ pub fn lsl(self : BigInt, n : Int) -> BigInt {
if r != 0 {
let mut carry = 0UL
for i = 0; i < self.len; i = i + 1 {
carry = carry.lor(a[i].to_uint64().lsl(r))
carry = carry | a[i].to_uint64().lsl(r)
new_limbs[i + lz] = (carry % radix).to_uint()
carry = carry.lsr(radix_bit_len)
}
Expand All @@ -456,13 +456,6 @@ pub fn lsl(self : BigInt, n : Int) -> BigInt {
/// The sign of the result is the same as the sign of the input.
/// Only the absolute value is shifted.
pub fn op_shl(self : BigInt, n : Int) -> BigInt {
self.shl(n)
}

/// Left shift a bigint
/// The sign of the result is the same as the sign of the input.
/// Only the absolute value is shifted.
pub fn shl(self : BigInt, n : Int) -> BigInt {
if n < 0 {
abort("negative shift count")
}
Expand All @@ -478,7 +471,7 @@ pub fn shl(self : BigInt, n : Int) -> BigInt {
if r != 0 {
let mut carry = 0UL
for i = 0; i < self.len; i = i + 1 {
carry = carry.lor(a[i].to_uint64().lsl(r))
carry = carry | a[i].to_uint64().lsl(r)
new_limbs[i + lz] = (carry % radix).to_uint()
carry = carry.lsr(radix_bit_len)
}
Expand All @@ -495,17 +488,17 @@ pub fn shl(self : BigInt, n : Int) -> BigInt {
}
}

/// Right shift a bigint
/// Left shift a bigint
/// The sign of the result is the same as the sign of the input.
/// Only the absolute value is shifted.
pub fn op_shr(self : BigInt, n : Int) -> BigInt {
self.shr(n)
pub fn shl(self : BigInt, n : Int) -> BigInt {
self << n
}

/// Right shift a bigint
/// The sign of the result is the same as the sign of the input.
/// Only the absolute value is shifted.
pub fn shr(self : BigInt, n : Int) -> BigInt {
pub fn op_shr(self : BigInt, n : Int) -> BigInt {
if n < 0 {
abort("negative shift count")
}
Expand Down Expand Up @@ -543,6 +536,13 @@ pub fn shr(self : BigInt, n : Int) -> BigInt {
}
}

/// Right shift a bigint
/// The sign of the result is the same as the sign of the input.
/// Only the absolute value is shifted.
pub fn shr(self : BigInt, n : Int) -> BigInt {
self >> n
}

pub fn asr(self : BigInt, n : Int) -> BigInt {
self >> n
}
Expand Down Expand Up @@ -614,7 +614,7 @@ pub fn to_string(self : BigInt) -> String {
for i = self.len - 1; i >= 0; i = i - 1 {
let mut x = self.limbs[i].to_uint64().to_int64()
for j = 0; j < v_idx; j = j + 1 {
let y = v[j].lsl(radix_bit_len).lor(x)
let y = v[j].lsl(radix_bit_len) | x
x = y / decimal_mask
v[j] = y % decimal_mask
}
Expand Down Expand Up @@ -829,18 +829,16 @@ pub fn BigInt::from_octets(input : Bytes, ~signum : Int = 1) -> BigInt {
let limbs = FixedArray::make(limbs_len, 0U)
// head at most significant limb
for i = 0; i < mod / 8; i = i + 1 {
limbs[limbs_len - 1] = limbs[limbs_len - 1]
.lsl(8)
.lor(input[i].to_int().reinterpret_as_uint())
limbs[limbs_len - 1] = limbs[limbs_len - 1].lsl(8) |
input[i].to_int().reinterpret_as_uint()
}
let byte_per_limb = radix_bit_len / 8
// tail
for i = 0; i < div; i = i + 1 {
for j = 0; j < byte_per_limb; j = j + 1 {
let bytes_idx = len - byte_per_limb - i * byte_per_limb + j
limbs[i] = limbs[i]
.lsl(8)
.lor(input[bytes_idx].to_int().reinterpret_as_uint())
limbs[i] = limbs[i].lsl(8) |
input[bytes_idx].to_int().reinterpret_as_uint()
}
}
if limbs[limbs_len - 1] == 0 {
Expand Down Expand Up @@ -879,7 +877,7 @@ pub fn BigInt::to_octets(self : BigInt, ~length? : Int) -> Bytes {
let len = max(length, len)
let result = Bytes::new(len)
for i = 0; i < len && i / 4 < self.len; i = i + 1 {
result[len - 1 - i] = (self.limbs[i / 4].shr(i % 4 * 8) & 0xffU)
result[len - 1 - i] = ((self.limbs[i / 4] >> (i % 4 * 8)) & 0xffU)
.reinterpret_as_int()
.to_byte()
}
Expand Down
21 changes: 9 additions & 12 deletions builtin/bigint_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -377,21 +377,18 @@ test "lsl" {

test "shr" {
let a = BigInt::from_int64(1234567890123456789L)
let b = a.shr(1)
let b = a >> 1
inspect!(b.to_string(), content="617283945061728394")
let c = a.shr(64)
let c = a >> 64
inspect!(c.to_string(), content="0")
let a = BigInt::from_int64(-1234567890123456789L)
let b = a.shr(1)
let b = a >> 1
inspect!(b.to_string(), content="-617283945061728395")
let c = a.shr(64)
let c = a >> 64
inspect!(c.to_string(), content="-1")
assert_eq!(
BigInt::from_int64(0b1111_1111L).shr(4),
BigInt::from_int64(0b1111L),
)
assert_eq!(BigInt::from_int64(0b1111_1111L).shr(24), BigInt::from_int64(0))
assert_eq!(BigInt::from_int64(0b1111_1111L).shr(44), BigInt::from_int64(0))
assert_eq!(BigInt::from_int64(0b1111_1111L) >> 4, BigInt::from_int64(0b1111L))
assert_eq!(BigInt::from_int64(0b1111_1111L) >> 24, BigInt::from_int64(0))
assert_eq!(BigInt::from_int64(0b1111_1111L) >> 44, BigInt::from_int64(0))
}

test "decimal_string" {
Expand Down Expand Up @@ -567,12 +564,12 @@ test "panic op_mod coverage for modulo by zero" {

test "panic shl coverage for negative shift" {
let a = BigInt::from_int(123456789)
a.shl(-1) |> ignore
a << -1 |> ignore
}

test "panic lsr coverage for negative shift" {
let a = BigInt::from_int(123456789)
a.shl(-1) |> ignore
a << -1 |> ignore
}

test "panic from_string coverage for empty string" {
Expand Down
10 changes: 5 additions & 5 deletions builtin/bigint_wbtest.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -397,14 +397,14 @@ test "shl" {

test "shr" {
let a = BigInt::from_int64(1234567890123456789L)
let b = a.shr(1)
let b = a >> 1
check_len!(b)
inspect!(b.to_string(), content="617283945061728394")
let c = a.shr(64)
let c = a >> 64
check_len!(c)
inspect!(c.to_string(), content="0")
let a = BigInt::from_int64((radix * radix / 2).to_int64())
let b = a.shr(radix_bit_len * 2)
let b = a >> (radix_bit_len * 2)
check_len!(b)
inspect!(b.to_string(), content="0")
}
Expand Down Expand Up @@ -813,12 +813,12 @@ test "panic op_mod coverage for modulo by zero" {

test "panic shl coverage for negative shift" {
let a = BigInt::from_int(123456789)
a.shl(-1) |> ignore
a << -1 |> ignore
}

test "panic shr coverage for negative shift" {
let a = BigInt::from_int(123456789)
a.shr(-1) |> ignore
a >> -1 |> ignore
}

test "panic from_string coverage for empty string" {
Expand Down
18 changes: 9 additions & 9 deletions builtin/byte_test.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,19 @@ test "byte_lsr" {
}

test "byte_lxor" {
assert_eq!(b'\xFF'.lxor(b'\xFF'), b'\x00')
assert_eq!(b'\xFF'.lxor(b'\x0F'), b'\xF0')
assert_eq!(b'\x0F'.lxor(b'\xFF'), b'\xF0')
assert_eq!(b'\xFF' ^ b'\xFF', b'\x00')
assert_eq!(b'\xFF' ^ b'\x0F', b'\xF0')
assert_eq!(b'\x0F' ^ b'\xFF', b'\xF0')
}

test "byte_lor" {
assert_eq!(b'\xFF'.lor(b'\xFF'), b'\xFF')
assert_eq!(b'\xFF'.lor(b'\x0F'), b'\xFF')
assert_eq!(b'\x0F'.lor(b'\xFF'), b'\xFF')
assert_eq!(b'\xFF' | b'\xFF', b'\xFF')
assert_eq!(b'\xFF' | b'\x0F', b'\xFF')
assert_eq!(b'\x0F' | b'\xFF', b'\xFF')
}

test "byte_land" {
assert_eq!(b'\xFF'.land(b'\xFF'), b'\xFF')
assert_eq!(b'\xFF'.land(b'\x0F'), b'\x0F')
assert_eq!(b'\x0F'.land(b'\xFF'), b'\x0F')
assert_eq!(b'\xFF' & b'\xFF', b'\xFF')
assert_eq!(b'\xFF' & b'\x0F', b'\x0F')
assert_eq!(b'\x0F' & b'\xFF', b'\x0F')
}
4 changes: 2 additions & 2 deletions builtin/bytes.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ pub fn set_utf16_char(self : Bytes, offset : Int, value : Char) -> Int {
2
} else if code < 0x110000 {
let hi = code - 0x10000
let lo = hi.lsr(10).lor(0xD800)
let hi = hi.land(0x3FF).lor(0xDC00)
let lo = hi.lsr(10) | 0xD800
let hi = (hi & 0x3FF) | 0xDC00
self[offset] = lo.land(0xFF).to_byte()
self[offset + 1] = lo.lsr(8).to_byte()
self[offset + 2] = hi.land(0xFF).to_byte()
Expand Down
21 changes: 9 additions & 12 deletions builtin/hasher.mbt
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,14 @@ fn consume1(self : Hasher, input : Byte) -> Unit {
}

fn rotl(x : Int, r : Int) -> Int {
x.lsl(r).lor(x.lsr(32 - r))
x.lsl(r) | x.lsr(32 - r)
}

fn endian32(input : Bytes, cur : Int) -> Int {
input[cur + 0]
.to_int()
.lor(
input[cur + 1]
.to_int()
.lsl(8)
.lor(input[cur + 2].to_int().lsl(16).lor(input[cur + 3].to_int().lsl(24))),
input[cur + 0].to_int() |
(
input[cur + 1].to_int().lsl(8) |
(input[cur + 2].to_int().lsl(16) | input[cur + 3].to_int().lsl(24))
)
}

Expand All @@ -148,13 +145,13 @@ pub impl Hash for Bytes with hash_combine(self, hasher) {

// https://github.com/skeeto/hash-prospector
pub impl Hash for Int with hash(self) {
let mut x = self.lxor(self.lsr(17))
let mut x = self ^ self.lsr(17)
x = x * 0xed5ad4bb
x = x.lxor(x.lsr(11))
x = x ^ x.lsr(11)
x = x * 0xac4c1b51
x = x.lxor(x.lsr(15))
x = x ^ x.lsr(15)
x = x * 0x31848bab
x = x.lxor(x.lsr(14))
x = x ^ x.lsr(14)
x
}

Expand Down
Loading

0 comments on commit fe49546

Please sign in to comment.