Skip to content

Commit 517e4f5

Browse files
committed
also implement left shifts for {u,i}256
1 parent 5d8b135 commit 517e4f5

File tree

2 files changed

+64
-8
lines changed

2 files changed

+64
-8
lines changed

libm/src/math/support/big.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,6 @@ macro_rules! impl_common {
109109
}
110110
}
111111

112-
impl ops::Shl<u32> for $ty {
113-
type Output = Self;
114-
115-
fn shl(self, _rhs: u32) -> Self::Output {
116-
unimplemented!("only used to meet trait bounds")
117-
}
118-
}
119-
120112
impl ops::Add<Self> for $ty {
121113
type Output = Self;
122114

@@ -149,6 +141,32 @@ macro_rules! impl_common {
149141
}
150142
}
151143

144+
impl ops::Shl<u32> for $ty {
145+
type Output = Self;
146+
147+
fn shl(mut self, rhs: u32) -> Self::Output {
148+
debug_assert!(rhs < Self::BITS, "attempt to shift left with overflow");
149+
150+
let half_bits = Self::BITS / 2;
151+
let low_mask = half_bits - 1;
152+
let s = rhs & low_mask;
153+
154+
let lo = self.lo;
155+
let hi = self.hi;
156+
157+
self.lo = lo << s;
158+
159+
if rhs & half_bits == 0 {
160+
self.hi = (lo >> (low_mask ^ s) >> 1) as _;
161+
self.hi |= hi << s;
162+
} else {
163+
self.hi = self.lo as _;
164+
self.lo = 0;
165+
}
166+
self
167+
}
168+
}
169+
152170
impl ops::Shr<u32> for $ty {
153171
type Output = Self;
154172

libm/src/math/support/big/tests.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,41 @@ fn i256_ord() {
298298
assert!([wx, wx + _1, wx + _2, wy - _2, wy - _1, wy].is_sorted());
299299
}
300300
}
301+
302+
#[test]
303+
fn u256_shifts() {
304+
let _1 = u256::ONE;
305+
for k in 0..255 {
306+
let x = _1 << k;
307+
let x2 = _1 << (k + 1);
308+
assert!(x < x2);
309+
assert_eq!(x << 1, x2);
310+
assert_eq!(x + x, x2);
311+
assert_eq!(x >> k, _1);
312+
assert_eq!(x2 >> (k + 1), _1);
313+
}
314+
}
315+
#[test]
316+
fn i256_shifts() {
317+
let _1 = i256::ONE;
318+
for k in 0..254 {
319+
let x = _1 << k;
320+
let x2 = _1 << (k + 1);
321+
assert!(x < x2);
322+
assert_eq!(x << 1, x2);
323+
assert_eq!(x + x, x2);
324+
assert_eq!(x >> k, _1);
325+
assert_eq!(x2 >> (k + 1), _1);
326+
}
327+
328+
let min = _1 << 255;
329+
assert_eq!(min, i256::MIN);
330+
let mut x = min;
331+
for k in 0..255 {
332+
assert_eq!(x, min >> k);
333+
let y = x >> 1;
334+
assert_eq!(y + y, x);
335+
assert!(x < y);
336+
x = y;
337+
}
338+
}

0 commit comments

Comments
 (0)