Skip to content

Commit c53ee3c

Browse files
committed
Add bigint shr
1 parent a781ea0 commit c53ee3c

File tree

3 files changed

+112
-10
lines changed

3 files changed

+112
-10
lines changed

src/float/div.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,8 @@ where
332332
b_significand,
333333
);
334334

335-
// Transform to a fixed-point representation. We know this is in the range [1.0, 2.0] since
336-
// the explicit bit is set.
335+
// Transform to a fixed-point representation by shifting the significand to the high bits. We
336+
// know this is in the range [1.0, 2.0] since the explicit bit is set above.
337337
let b_uq1 = b_significand << (F::BITS - significand_bits - 1);
338338

339339
println!("b_uq1: {:#034x}", b_uq1);
@@ -632,6 +632,9 @@ where
632632
F::from_repr(abs_result | quotient_sign)
633633
}
634634

635+
/// Perform one iteration at any width.
636+
///
637+
/// Given
635638
fn iter_once<I>(x_uq0: I, b_uq1: I) -> I
636639
where
637640
I: Int + HInt,

src/int/big.rs

+45-8
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,56 @@ macro_rules! impl_common {
9696
unimplemented!("only used to meet trait bounds")
9797
}
9898
}
99-
100-
impl ops::Shr<u32> for $ty {
101-
type Output = Self;
102-
103-
fn shr(self, rhs: u32) -> Self::Output {
104-
unimplemented!("only used to meet trait bounds")
105-
}
106-
}
10799
};
108100
}
109101

110102
impl_common!(i256);
111103
impl_common!(u256);
104+
extern crate std;
105+
use std::dbg;
106+
107+
impl ops::Shr<u32> for u256 {
108+
type Output = Self;
109+
110+
fn shr(self, rhs: u32) -> Self::Output {
111+
debug_assert!(rhs < Self::BITS, "attempted to shift right with overflow");
112+
113+
if rhs >= Self::BITS {
114+
// Only happens when not in debug mode
115+
return Self::ZERO;
116+
}
117+
118+
if rhs == 0 {
119+
return self;
120+
}
121+
122+
let mut ret = self;
123+
let byte_shift = rhs / 64;
124+
let bit_shift = rhs % 64;
125+
126+
dbg!(self, rhs, byte_shift, bit_shift);
127+
128+
for idx in 0..4 {
129+
let base_idx = idx + byte_shift as usize;
130+
dbg!(base_idx);
131+
132+
let Some(base) = ret.0.get(base_idx) else {
133+
continue;
134+
};
135+
dbg!(base);
136+
137+
let mut new_val = base >> bit_shift;
138+
139+
if let Some(new) = ret.0.get(base_idx + 1) {
140+
new_val |= new.overflowing_shl(64 - bit_shift).0;
141+
}
142+
143+
ret.0[idx] = new_val;
144+
}
145+
146+
ret
147+
}
148+
}
112149

113150
macro_rules! word {
114151
(1, $val:expr) => {

testcrate/tests/big.rs

+62
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,65 @@ fn widen_mul_u128() {
5959
}
6060
assert!(errors.is_empty());
6161
}
62+
63+
#[test]
64+
fn not_u128() {
65+
assert_eq!(!u256::ZERO, u256::MAX);
66+
}
67+
68+
#[test]
69+
fn shr_u128() {
70+
let lo_a = [1, 2, 3, 10, u16::MAX as u128, u32::MAX as u128, u128::MAX];
71+
let b = [0, 1, 2, 4, 10, 31, 32, 33, 64, 96, 127];
72+
73+
let mut errors = Vec::new();
74+
75+
for a in lo_a {
76+
for b in b {
77+
let res = a.widen() >> b;
78+
let expected = (a >> b).widen();
79+
if res != expected {
80+
errors.push((a, b, res, expected));
81+
}
82+
}
83+
}
84+
85+
for (a, b, res, expected) in &errors {
86+
eprintln!(
87+
"FAILURE: {a:#034x} >> {b} = {} got {}",
88+
hexu(*expected),
89+
hexu(*res),
90+
);
91+
}
92+
assert!(errors.is_empty());
93+
}
94+
95+
// #[test]
96+
// fn shr_u128() {
97+
// let tests = [
98+
// (u128::MAX / 2, 2_u128, u256([u64::MAX - 1, u64::MAX, 0, 0])),
99+
// (u128::MAX, 2_u128, u256([u64::MAX - 1, u64::MAX, 1, 0])),
100+
// (u128::MAX, u128::MAX, u256([1, 0, u64::MAX - 1, u64::MAX])),
101+
// (u128::MIN, u128::MIN, u256::ZERO),
102+
// (1234, 0, u256::ZERO),
103+
// (0, 1234, u256::ZERO),
104+
// ];
105+
106+
// let mut errors = Vec::new();
107+
// for (i, (a, b, exp)) in tests.iter().copied().enumerate() {
108+
// let res = a.widen_mul(b);
109+
// assert_eq!(res, res_z);
110+
// if res != exp {
111+
// errors.push((i, a, b, exp, res));
112+
// }
113+
// }
114+
115+
// for (i, a, b, exp, res) in &errors {
116+
// eprintln!(
117+
// "FAILURE ({i}): {a:#034x} * {b:#034x} = {} got {}",
118+
// hexu(*exp),
119+
// hexu(*res)
120+
// );
121+
// }
122+
// assert!(errors.is_empty());
123+
// }

0 commit comments

Comments
 (0)