| 68 | |
| 69 | #[pymethod] |
| 70 | fn getrandbits(&self, k: PyObjectRef, vm: &VirtualMachine) -> PyResult<BigInt> { |
| 71 | let k_int = k.try_index(vm)?; |
| 72 | let k_bigint = k_int.as_bigint(); |
| 73 | if k_bigint.is_negative() { |
| 74 | return Err(vm.new_value_error("number of bits must be non-negative")); |
| 75 | } |
| 76 | let k: isize = k_int |
| 77 | .try_to_primitive(vm) |
| 78 | .map_err(|_| vm.new_overflow_error("getrandbits: number of bits too large"))?; |
| 79 | match k { |
| 80 | 0 => Ok(BigInt::zero()), |
| 81 | mut k => { |
| 82 | let mut rng = self.rng.lock(); |
| 83 | let mut gen_u32 = |k| { |
| 84 | let r = rng.next_u32(); |
| 85 | if k < 32 { r >> (32 - k) } else { r } |
| 86 | }; |
| 87 | |
| 88 | let words = (k - 1) / 32 + 1; |
| 89 | let word_array = (0..words) |
| 90 | .map(|_| { |
| 91 | let word = gen_u32(k); |
| 92 | k = k.wrapping_sub(32); |
| 93 | word |
| 94 | }) |
| 95 | .collect::<Vec<_>>(); |
| 96 | |
| 97 | let uint = BigUint::new(word_array); |
| 98 | // very unlikely but might as well check |
| 99 | let sign = if uint.is_zero() { |
| 100 | Sign::NoSign |
| 101 | } else { |
| 102 | Sign::Plus |
| 103 | }; |
| 104 | Ok(BigInt::from_biguint(sign, uint)) |
| 105 | } |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | #[pymethod] |
| 110 | fn getstate(&self, vm: &VirtualMachine) -> PyTupleRef { |