1use crate::ubig::UBig;
2use alloc::vec;
3use dashu_base::{DivRem, PowerOfTwo};
4
5impl UBig {
6 pub fn remove(&mut self, factor: &UBig) -> Option<usize> {
11 if self.is_zero() || factor.is_zero() || factor.is_one() {
12 return None;
13 }
14
15 if factor.is_power_of_two() {
17 let bits = factor.trailing_zeros().unwrap();
18 let exp = self.trailing_zeros().unwrap() / bits;
19 *self >>= exp * bits;
20 return Some(exp);
21 }
22
23 let (mut q, r) = (&*self).div_rem(factor);
24 if !r.is_zero() {
25 return Some(0);
26 }
27
28 let mut exp = 1;
30 let mut pows = vec![factor.sqr()];
31 loop {
32 let last = pows.last().unwrap();
33 let (new_q, r) = (&q).div_rem(last);
34 if !r.is_zero() {
35 break;
36 }
37
38 exp += 1 << pows.len();
39 q = new_q;
40 let next_sq = last.sqr();
41 pows.push(next_sq);
42 }
43
44 while let Some(last) = pows.pop() {
46 let (new_q, r) = (&q).div_rem(last);
47 if r.is_zero() {
48 exp += 1 << (pows.len() + 1);
49 q = new_q;
50 }
51 }
52
53 let (new_q, r) = (&q).div_rem(factor);
55 if r.is_zero() {
56 exp += 1;
57 q = new_q;
58 }
59
60 *self = q;
61 Some(exp)
62 }
63}