algostru/arithmetic/multiplication/karatsuba.rs
1use std::cmp;
2
3use num_integer::Integer;
4use num_bigint::BigInt;
5
6/// Karatsuba implementation
7fn karatsuba(x: BigInt, y: BigInt) -> BigInt {
8 let x_len = x.to_str_radix(10).len() as u32;
9 let y_len = y.to_str_radix(10).len() as u32;
10 let n = cmp::min(x_len, y_len);
11
12 if n == 1 {
13 return x * y;
14 }
15
16 let midpoint = n / 2;
17 let base = BigInt::from(10);
18 let midnum = base.pow(midpoint);
19
20 let a = x.div_floor(&midnum);
21 let b = x.mod_floor(&midnum);
22 let c = y.div_floor(&midnum);
23 let d = y.mod_floor(&midnum);
24
25 let p = &a + &b;
26 let q = &c + &d;
27
28 let ac = karatsuba(a, c);
29 let bd = karatsuba(b, d);
30 let pq = karatsuba(p, q);
31
32 let adbc = &pq - &ac - &bd;
33
34 base.pow(2 * midpoint) * ac + base.pow(midpoint) * adbc + bd
35}
36
37/// Karatsuba Multiplication
38///
39/// Input: two n-digit positive integers x and y
40/// Output: product of x * y
41/// Assumption: n is power of 2
42///
43/// ================================================================================================
44///
45/// ```ignore
46/// n = max length of x or y
47///
48/// if n equals 1 then
49/// base case: return product of x * y
50/// else
51/// a, b = first and second halves (n/2) of x
52/// c, d = first and second halves (n/2) of y
53///
54/// p = sum of a and b
55/// q = sum of c and d
56///
57/// recursive karatsuba:
58/// ac = product of a * c
59/// bd = product of b * d
60/// pq = product of p * q
61///
62/// adbc = pq - ac - bd
63///
64/// return result: 10^n * ac + (10^n/2) * adbc + bd
65/// ```
66pub fn multiply(x: BigInt, y: BigInt) -> BigInt {
67 karatsuba(x, y)
68}