Skip to content

Commit 499283e

Browse files
authored
math.unsigned: fix lsh() for uint256, add tests (#24867)
1 parent 09e1edb commit 499283e

File tree

2 files changed

+37
-11
lines changed

2 files changed

+37
-11
lines changed

vlib/math/unsigned/uint256.v

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -259,18 +259,32 @@ pub fn (u Uint256) rsh(n u32) Uint256 {
259259
}
260260

261261
// lsh returns a new Uint256 that has been left bit shifted
262-
pub fn (u Uint256) lsh(n_ u32) Uint256 {
263-
mut n := n_
264-
if n > 128 {
265-
return Uint256{u.lo.lsh(n - 128), uint128_zero}
266-
}
267-
268-
if n > 64 {
269-
n -= 64
270-
return Uint256{Uint128{u.lo.lo << n, 0}, Uint128{u.lo.hi << n | u.lo.lo >> (64 - n), u.hi.lo << n | u.lo.hi >> (64 - n)}}
262+
pub fn (u Uint256) lsh(n u32) Uint256 {
263+
mut s := Uint256{}
264+
if n == 0 {
265+
s.lo = u.lo
266+
s.hi = u.hi
267+
} else if n >= 256 {
268+
s.lo = uint128_zero
269+
s.hi = uint128_zero
270+
} else if n == 128 {
271+
s.lo = uint128_zero
272+
s.hi = u.lo
273+
} else if n > 128 {
274+
s.lo = uint128_zero
275+
s.hi = u.lo.lsh(n - 128)
276+
} else if n == 64 {
277+
s.lo = Uint128{0, u.lo.lo}
278+
s.hi = Uint128{u.lo.hi, u.hi.lo}
279+
} else if n > 64 {
280+
shift := n - 64
281+
s.lo = Uint128{0, u.lo.lo << shift}
282+
s.hi = Uint128{u.lo.lo >> (64 - shift) | u.lo.hi << shift, u.lo.hi >> (64 - shift) | u.hi.lo << shift}
283+
} else {
284+
s.lo = Uint128{u.lo.lo << n, u.lo.hi << n | u.lo.lo >> (64 - n)}
285+
s.hi = Uint128{u.hi.lo << n | u.lo.hi >> (64 - n), u.hi.hi << n | u.hi.lo >> (64 - n)}
271286
}
272-
273-
return Uint256{Uint128{u.lo.lo << n, u.lo.hi << n | u.lo.lo >> (64 - n)}, Uint128{u.hi.lo << n | u.lo.hi >> (64 - n), u.hi.hi << n | u.hi.lo >> (64 - n)}}
287+
return s
274288
}
275289

276290
// div - untested

vlib/math/unsigned/uint256_test.v

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,15 @@ fn test_rsh() {
291291
assert '170141183460469231731687303715884105727' == a.rsh(129).str()
292292
assert unsigned.uint256_zero == a.rsh(256)
293293
}
294+
295+
fn test_lsh() {
296+
a := unsigned.uint256_from_dec_str('123')!
297+
assert a.lsh(0).str() == a.str()
298+
assert a.lsh(1).str() == '246'
299+
assert a.lsh(63).str() == '1134474760533137424384'
300+
assert a.lsh(64).str() == '2268949521066274848768'
301+
assert a.lsh(100).str() == '155921023828072216384094494261248'
302+
assert a.lsh(128).str() == '41854731131275431005995076714107490009088'
303+
assert a.lsh(200).str() == '197653379443855803891661337357963000110230968235283518742069248'
304+
assert a.lsh(300) == unsigned.uint256_zero
305+
}

0 commit comments

Comments
 (0)