1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use std::{
fmt::{Display, Formatter},
ops::Mul,
};
use num::{BigInt, Integer, Signed, ToPrimitive};
mod shift_add;
mod steps;
#[derive(Debug)]
pub struct MultiplicationSteps {
base: u32,
lhs: BigInt,
rhs: BigInt,
result: BigInt,
steps: Vec<ShiftAdd>,
}
#[derive(Debug)]
pub struct ShiftAdd {
result: BigInt,
tail_digits: usize,
}
pub fn v_mul_detailed(a: &BigInt, b: &BigInt, base: u32) -> MultiplicationSteps {
let lhs = get_digits_rev(a, base);
let rhs = get_digits_rev(b, base);
let mut steps = MultiplicationSteps::new(a, b).with_base(base);
for (tail_rhs, dx) in rhs.iter().enumerate() {
for (tail_lhs, dy) in lhs.iter().enumerate() {
steps.push_step(ShiftAdd::new(dx.mul(dy), tail_rhs + tail_lhs))
}
}
steps
}
pub fn v_mul(a: &BigInt, b: &BigInt, base: u32) -> MultiplicationSteps {
let rhs = get_digits_rev(b, base);
let mut steps = MultiplicationSteps::new(a, b).with_base(base);
for (tail_rhs, dy) in rhs.iter().enumerate() {
steps.push_step(ShiftAdd::new(a.mul(BigInt::from(*dy)), tail_rhs))
}
steps
}
fn get_digits_rev(num: &BigInt, base: u32) -> Vec<usize> {
let mut digits = Vec::new();
let mut num = num.clone();
while num.is_positive() {
let (q, r) = num.div_rem(&BigInt::from(base));
digits.push(r.to_usize().unwrap());
num = q;
}
digits
}