problem statement.

Typically, we assume that basic operations on natural numbers (e.g., adding or multiplying two natural numbers together) are performed in constant time. In practice, this assumption is correct whenever we restrict ourselves to natural numbers with some maximum size (e.g., 64 bit natural numbers, for which basic operations are supported directly by modern processors). Applications such as cryptography often work with huge natural numbers, however (e.g., 4048 bit values, which can hold a maximum of ). Hence, for these applications we can no longer assume that operations on natural numbers are in constant time: these applications require the development of efficient algorithms even for basic operations on natural numbers.

Consider two -digit natural numbers and written in base 10: the digits and each have a value in . For example, if , then we could have , in which case .

1.1

Write an algorithm ADD(A, B) that computes in . Explain why your algorithm is correct and the runtime complexity is .

Assumption: one converts and into two arrays of integers, and .

Algorithm 20 ADD(A, B)

Input: A[a1an]A \coloneqq \lbrack a_{1} \dots a_{n} \rbrack

Input: B[b1bn]B \coloneqq \lbrack b_{1} \dots b_{n} \rbrack

1:C[ ] where C=n+1C \gets \lbrack \space \rbrack \text{ where } |C| = n + 1

2:carry0carry \gets 0

3:in1i \gets n-1

4:while i0i \geq 0 do

5:C[i+1](ai+bi+carry)mod10C[i+1] \gets (a_{i} + b_{i} + carry) \mod 10

6:carry(ai+bi+carry)/10carry \gets \lfloor (a_{i} + b_{i} + carry) / 10 \rfloor

7:ii1i \gets i - 1

8:end while

9:C[0]carryC[0] \gets carry

10:if C[0]==0C[0] == 0 then

11:CC[1n]C \gets C[1 \dots n]

12:end if

Output: CC

Runtime complexity:

  • L1 takes time to initialise.
  • while loop iterates times, each iteration perform constant time operations (additions, modulo, division) in time.
  • Finally, the adjustment of the output array takes time.

Thus, total runtime complexity is .

Correctness:

Invariants:

where defines as the carry value resulting from the addition.

bound function starts at

Proof

Base case: (L2,3)

Invariant for carry holds, as

Now we will prove these invariants still hold til reach the end of m-th loop:

Assuming the invariants hold at the start of m-th loop, or:

L4-7: The while loop.

  • Carry forward invariants holds
  • , or holds correct digits after addition of and carry
  • strictly decreases after each iteration,

Therefore the invariants holds.

1.2

What is the runtime complexity of this algorithm in terms of the number of digits in A and B?

Runtime complexity is , where is the number of digits in and .

For each digits of , it multiply every digits of , which results in operations.

Each addition operation takes at most digit additions, and we perform of these additions, therefore resulting in time.

Overall, pen-and-paper addition of two -digit numbers takes time.

1.3

Let be an -digit number with . Hence, where the first digits of C and is the remaining digits of C. For example, if , then and

Using the breakdown of a number into their high and low part, one notices the following

Here is the following recursive algorithm BREAKSDOWNMULTIPLY(A, B) that computes :

Algorithm 21 BREAKSDOWNMULTIPLY(A, B)

Input: A and B have n=2m digitsA \text{ and } B \text{ have } n=2m \text{ digits}

1:if n=1n = 1 then

2:return a1×b1a_{1} \times b_{1}

3:else

4:hhBREAKSDOWNMULTIPLY(Ahigh,Bhigh)hh \coloneqq \text{BREAKSDOWNMULTIPLY}(A_{\text{high}}, B_{\text{high}})

5:hlBREAKSDOWNMULTIPLY(Ahigh,Blow)hl \coloneqq \text{BREAKSDOWNMULTIPLY}(A_{\text{high}}, B_{\text{low}})

6:lhBREAKSDOWNMULTIPLY(Alow,Bhigh)lh \coloneqq \text{BREAKSDOWNMULTIPLY}(A_{\text{low}}, B_{\text{high}})

7:llBREAKSDOWNMULTIPLY(Alow,Blow)ll \coloneqq \text{BREAKSDOWNMULTIPLY}(A_{\text{low}}, B_{\text{low}})

8:return hh102m+(hl+lh)10m+llhh \cdot 10^{2m} + (hl + lh) \cdot 10^m + ll

9:end if

10:return A×BA \times B

Prove that algorithm BREAKSDOWNMULTIPLY(A, B) is correct.

The proposed BREAKSDOWNMULTIPLY(A, B) is a variant of Karatsuba’s algorithm.

Base case: , which implies are correct (multiplication of two two-digits number).

Through recursions, at any level , one would observe:

The recursive call correctly computes the product of til the base case.

The combination of the products is proven through previous math steps, therefore, the algorithm is correct.

1.4

Give a recurrence for the runtime complexity of BREAKSDOWNMULTIPLY(A, B) Explain each term in the recurrence.

Draw a recurrence tree for and use this recurrence tree to solve the recurrence by proving that for some function

What is the runtime complexity of BREAKSDOWNMULTIPLY(A, B)? Do you expect this algorithm to be faster than the pen-and-paper multiplication algorithm? Hint: Feel free to assume that . Feel free to assume that we can add two -digit number in (e.g., using ADD) and that we can multiply a -digit number with in .

For two digits number and , the recurrent is:

  • The base case when is , as it only performs a single digit multiplication, without no recursive calls.
  • The recursive case when performs 4 recursive calls, each with digits, each on number half the size of original input (since ), hence .
  • is the linear time complexity adding the products of the recursive calls, per our assumption that we can multiply a -digit number with in .

The recurrence tree for is:

T(n)
├── T(n/2)
   ├── T(n/4)
   ├── T(n/8)
   ├── ...
   ...
   ├── ...
   └── ...
  ...
   └── T(n/8)
   ├── T(n/4)
   ├── ...
   ├── ...
   ├── ...
   └── ...
   ├── T(n/4)
   ├── ...
   ├── ...
   ├── ...
   └── ...
   └── T(n/4)
       ├── ...
       ├── ...
       ├── ...
       └── ...
├── T(n/2)
   ├── ...
   ├── ...
   ├── ...
   └── ...
├── T(n/2)
   ├── ...
   ├── ...
   ├── ...
   └── ...
└── T(n/2)
    ├── ...
    ├── ...
    ├── ...
    └── ...
  • The total number of nodes at depth is , since each level of recursion calls the function four times.
  • Work done at level is , since work done per depth is times the number of nodes add that depth.
  • Depth of the tree is , since the input size is halved at each level.

Therefore, one can solve for :

Thus the runtime complexity of BREAKSDOWNMULTIPLY(A, B) is quadratic, .

From here, the algorithm is the same as the pen-and-paper multiplication algorithm, which also takes time.

1.5

One can observe

Hence by rearranging terms, one can conclude that

Based on conclusion above, can be seen as:

The final rewritten form of only requires three multiplication terms, namely

Use the observation to construct a recursive multiplication SMARTMATHSMULTIPLY(A, B) that only perform three recursive multiplications. Argue why SMARTMATHSMULTIPLY(A, B) is correct.

Algorithm 22 SMARTMATHSMULTIPLY(A, B)

Input: A and B have n=2m digitsA \text{ and } B \text{ have } n=2m \text{ digits}

1:if n=1n = 1 then

2:return a1×b1a_{1} \times b_{1}

3:else

4:hhSMARTMATHSMULTIPLY(Ahigh,Bhigh)hh \coloneqq \text{SMARTMATHSMULTIPLY}(A_{\text{high}}, B_{\text{high}})

5:llSMARTMATHSMULTIPLY(Alow,Blow)ll \coloneqq \text{SMARTMATHSMULTIPLY}(A_{\text{low}}, B_{\text{low}})

6:midSMARTMATHSMULTIPLY(Ahigh+Alow,Bhigh+Blow)mid \coloneqq \text{SMARTMATHSMULTIPLY}(A_{\text{high}} + A_{\text{low}}, B_{\text{high}} + B_{\text{low}})

7:return hh102m+(midhhll)10m+llhh \cdot 10^{2m} + (mid - hh - ll) \cdot 10^m + ll

8:end if

9:return A×BA \times B

The proposed SMARTMATHSMULTIPLY(A, B) is the basis of Karatsuba’s algorithm.

Base case: , which implies are correct (multiplication of two single digit number).

Assume that SMARTMATHSMULTIPLY(A, B) correctly computes the product of for with lest than digits.

The following invariants hold per recursive call:

  • where (true from problem statement and )
  • recursive call computes correctly, where for numbers fewer than digits (from induction hypothesis)
  • combination invariants: (true from previous statement)

Thus, the algorithm is correct.

1.6

Give a recurrence for the runtime complexity of SMARTMATHSMULTIPLY(A, B) Explain each term in the recurrence.

Solve the recurrence by proving that for some function . Use any methods that you find comfortable with.

What is the runtime complexity of SMARTMATHSMULTIPLY(A, B)? Do you expect this algorithm to be faster than the pen-and-paper multiplication algorithm? Hint: Feel free to assume that . Feel free to assume that we can add two -digit number in (e.g., using ADD) and that we can multiply a -digit number with in .

For two digits number and , the recurrent is:

  • The base case when is , as it only performs a single digit multiplication, without no recursive calls.
  • The recursive case when performs 3 recursive calls, each with digits, each on number half the size of original input (since ), hence .
  • is the linear time complexity adding the products of the recursive calls, per our assumption that we can multiply a -digit number with in .

Using Master Theorem, we can solve for , with .

The master theorem states that if , with , then .

Thus

Runtime complexity of SMARTMATHSMULTIPLY(A, B)

This algorithm is expected to be faster than the pen-and-paper multiplication algorithm, which also takes time.