vertical_multiplication/steps/
mod.rs

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