+ All Categories
Home > Documents > Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers...

Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers...

Date post: 18-May-2020
Category:
Upload: others
View: 3 times
Download: 0 times
Share this document with a friend
54
Software Implementation of Classical and Karatsuba Multiplications By Thanh V. Do Professor Kris Gaj Cryptography and Computer Network Security ECE543 December 8, 2000
Transcript
Page 1: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Software Implementation of Classical and Karatsuba Multiplications

By

Thanh V. Do

Professor Kris Gaj Cryptography and Computer Network Security

ECE543 December 8, 2000

Page 2: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

TABLE OF CONTENTS INTRODUCTION............................................................................................................. 3

Background..................................................................................................................... 3 Purpose............................................................................................................................ 3 Scope............................................................................................................................... 3

REPRESENTATION OF HIGH PRECISION NUMBERS......................................... 4 Data Storage ...................................................................................................................... 4 ALGORITHM: THE BASICS ........................................................................................ 5

Classical Multiplication of Two Same-Size Large Integers ........................................... 5 Karatsuba Multiplication of Two Same-Size Large Integers ......................................... 5

METHODOLOGY ........................................................................................................... 8 Timing Program.............................................................................................................. 8 Cycle Counting Program................................................................................................. 9

OBSERVATIONS........................................................................................................... 10 RESULTS ........................................................................................................................ 11 APPENDIX A – Program Test ...................................................................................... 12

Header File.................................................................................................................... 12 Implementation File ...................................................................................................... 13 Program......................................................................................................................... 24 Result ............................................................................................................................ 26

APPENDIX B - Timing Test .......................................................................................... 28 Header File for the Timing Test.................................................................................... 28 Implementation File for the Timing Test...................................................................... 29 Timing Test Program .................................................................................................... 35 Timing Test Table......................................................................................................... 39

APPENDIX C - Cycle Count Test ................................................................................. 40 Header File for the Cycle Count Test ........................................................................... 41 Implementation File for Cycle Count Test ................................................................... 41 Cycle Count Test Program............................................................................................ 42 Cycle Counts Table....................................................................................................... 47

Page 3: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

INTRODUCTION Background The basic numerical data types provided in most languages (e.g., Pascal, Fortran, C, C++ …) are limited to a given precision which depends on the data type itself and the machine. As a consequence, the computation of a numerical constant with more than ten decimal digits needs specific development to handle high precision numbers. Several mathematical software package (e.g., Mathematica, Maple) directly provide the possibility to work with a non-limited precision. They are used to prototype algorithms. But they are also highly inefficient for practical purpose because they are not dedicated to the numerical computation. Standard computer libraries (in C or C++ for example) exist that are much more efficient for practical usage. Most of these are dedicated to the computations with a reasonable number of digits of less than 1000 decimal digits and suffer from the fact that efficient algorithms on very large number are not implemented. Several isolated computer libraries in high-level languages (C or C++) such as LiDIA exist that are much more efficient. They are dedicated to computation of large numbers. Nevertheless, it’s still of interest to know how to handle high precision numbers by implementing it yourself to have an idea about the complexity of the problem. Purpose In this paper, I will discuss the implementations of Karatsuba and classical multiplication of large numbers. I will focus on the performance measurements of the operations. Scope The Karatsuba and classical methods of multiplying two large integers were implemented. This implementation is dependent on the data type and machine. The speed of the algorithm depends on the speed, memory, ect., of the machine. The LiDIA library (the Library for Computational Number Theory from http://www.informatik.tu-darmstadt.de/TI/LiDIA/) was used to check if the codes produce the correct results. Performance measurements were then taken. These measurements were analyzed to determine the cut-off point for the use of Karatsuba multiplications.

December 15, 2000 Page 3 of 54

Page 4: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

REPRESENTATION OF HIGH PRECISION NUMBERS In C++ 6.0, the maximum integer is 4294967295 (or FFFFFFFF in hexadecimal), which has 32 bits. For the computer basic word multiplication operation, the multiplicand and multiplier can be at most ½ of the maximum word size. Thus the maximum length of the word size is 16-bit long. The data type is UNSIGNED SHORT (16-bit long). Thus each digit of the number is in base 216. The array data structure was used to represent large numbers. For example, the large number representation is as follows: Large Number

6971178278295906333 = 10269*(216)0 + 36799*(216)1 + 39349*(216)2 + 24766*(216)3

Big Number (in base 216)

24766 39349 36799 10269

Data Storage

x0 = cell 0 of the array contains 10269 x1 = cell 1 of the array contains 36799 x2 = cell 2 of the array contains 39349 x3 = cell 3 of the array contains 24766

Thus a big integer N is in a given base 216: X = x0 + x1(216) + x2(216)2 + … + xn(216)n.

December 15, 2000 Page 4 of 54

Page 5: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

ALGORITHM: THE BASICS Classical Multiplication of Two Same-Size Large Integers Let n n

X = Σ xkBk Y = Σ ykBk

k=0 k=0

Then Z = X * Y can be obtained from the formula n n

Z = Σ Σ xkyj k=0 j=0

For large integers of size n, the classical multiplication is on the order of O(n2) complexity. It is thus of our interest to try to obtain a faster algorithm for multiplying two large integers. Karatsuba Multiplication of Two Same-Size Large Integers Using Karatsuba’s algorithm, we can make the multiplication of two large integers faster than O(n2). The technique is to use recursion. The divide-and conquer strategy is to break the problem into two simpler sub-problems of the same type, and then solve for these sub-problems. The final step is to merge all the partial results into the solution. Given two large number of the form: n n

X = Σ xkBk Y = Σ ykBk

k=0 k=0

Note that n should be 2α for some α. If n ≤ 2α, add 0 to those empty digits. We can multiply two large integer X and Y by breaking them into two parts of equal lengths. This gives the equalities X = x0 + x1Bm, Y = y0 + y1Bm, m = ½ n The product is then computed as: XY = x0y0 + (x0y1 + x1y0)Bm + x1y1B2m

December 15, 2000 Page 5 of 54

Page 6: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

Note that x0y1 + x1y0 = x0y0 + x1y1 - (x0 – x1)(y0 – y1). Now let P0 = x0y0, P1 = (x0 – x1)(y0 – y1), P2 = x1y1 So XY = P0 + (P0 + P2 - P1)Bm + P2B2m The illustration below depicts the basic step of the Karatsuba algorithm.

The recursive step is as follows:

This approach reduces the problem of multiplying n-digit numbers to only 3 multiplication operations of n/2, verse 4 in the classical algorithm. This approach also needs three subtraction and one addition operations of size n/2. The algorithm is performed recursively, so the total time is: T(n) = 3T(n/2) + cn, for some constant c which also implies that: T(2k) ≤ c(3k – 2k), for k ≥ 1, (by induction). Thus, T(n) ≤ T(2log

2n) ≤ c(3log

2n – 2 log

2n) ≤ 3c 3log

2n = 3cnlog

23 = O(nlog

23).

December 15, 2000 Page 6 of 54

Page 7: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

So the running time for the multiplication operation can be reduced from O(n2) to O(nlog

23) ≈ O(n1.57), which is much better when n is large.

December 15, 2000 Page 7 of 54

Page 8: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

METHODOLOGY Performance measurements were conducted in two different methods, as specified in the “Efficiency Testing of ANSI C Implementations of Round1 Candidate Algorithms for the Advanced Encryption Standard.” The “Timing Test” is the first method of testing performance which deals with the amount of time required to perform large integer multiplication operations. The second method, “Cycle Counting Test”, deals with the number of clock cycles required to perform the same operations. The Timing Test used the clock() timing mechanism in the C++ library to calculate the processor time consumed in the execution of the API calls and the measured multiplication operations (Classical, Karatsuba, and LiDIA multiplication). The Cycle Counting Test counted the actual clock cycles consumed in performing the multiplication operations. Assembly language code was used in the cycle counting test, which could turn off interrupts during testing. The result is very accurate. The cycle counting test eliminates the variability of the processor speed. In other words, the same number of clock cycles are required to perform a multiplication operation on the 150MHz Pentium II processor as it does on the 800MHz Pentitum III processor. Unfortunately, the cycle counting test could only be performed on the Intel processor based systems. For the project, the code was developed on an IBM ThinkPad 600X, 128MB RAM using MS Visual C++ 6.0 on Windows98. In order to double check the code, LiDIA was used. However, LiDIA is not supported on MS Windows98 and Visual C++ 6.0. The next step was to port the code to Dell Latitude Cpi 233X, 32MB RAM using G++ on Redhat Linux 6.1. Under this platform, LiDIA was supported. On this platform, test vectors were tested to determine if the code is correct. The code and output of the program are provided in Appendix A. Once the code was determined to be correct, it was used perform the timing and cycle counting test as described below (on an IBM ThinkPad 600X, 128MB RAM using MS Visual C++ 6.0 on Windows98). Timing Program For each digit size, two values are calculated:

December 15, 2000 Page 8 of 54

Page 9: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

• The time to perform the multiplication using the classical algorithm; and • The time to perform the multiplication using the Karatsuba algorithm.

The test program generates 1000 duples (i.e., sets of timing information) as described above for each digit size. The time values in each category are then sorted, and the median value is determined. A standard deviation is calculated for each test category. Finally, the average of all value that falls within three standard deviations of the median is determined. This value is then reported as the average time to perform the specific multiplication operation for each digit size. The result of the can be found in the Appendix B. Cycle Counting Program For each digit size, two values are calculated:

• The number of clock cycle to perform the multiplication using the classical algorithm; and

• The number of clock cycle to perform the multiplication using the Karatsuba algorithm.

These value were measured by placing the CPUID and RDTSC assembly language instructions around the tested operation. These instructions were called before the multiplication operation to “flush” the instruction cache. Additionally, the CLI and STI were used to switch interrupts off before the test and back on after the test. They would eliminates extraneous interrupts that would skew the results. Analysis of this data was preformed in the same way as the timing program described above. The result of the can be found in the Appendix C.

December 15, 2000 Page 9 of 54

Page 10: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

OBSERVATIONS After implementing the classical and Karatsuba algorithms, the program was tested using the LiDIA library to double check the results. The program automatically generated large numbers to be used for testing the efficiency of the implementation of the algorithms. Each digit of the number was separately generated. The most significant bit of the most significant digit was set to 1 to ensure the size of the number is within the range tested. The NIST’s Efficiency Testing was used to perform the timing harnesses of the implementation. The testing involves both the clock time and the cycle time. the test vector. The clock time was used to determine the cut-off value for which the Karatsuba algorithm runs faster than the Classical algorithm. The cycle time is used to compare the efficiency of the two algorithms. The code implemented the Karatsuba multiplication requires three time as much space as the classical method, and six times the size of the number of digits of the multiplicand or multiplier . This space is required for the recursion to work. The space usage is as follows: (assume n is the number of digits of the large number) Product of the two low halves

Product of the two high halves

Difference of two a’s halves

Difference of two b’s halves

Product of the two differences

Middle term of the Karatsuba algorithm

2n 2n ½ n ½ n n n In this implementation of the Karatsuba algorithm, the multiplication is quickest if the digit size is 2α. For other values, the code sets the digit size to the smallest 2α, and set those empty digit to zero. For example, if the digit size is 5, the Karatsuba algorithm will treat it as if it’s of size 8, and set the three significant digits to zero. Thus, the algorithm would make the same number of recursions for a number of 5 or 8 digits. Because the speed of the algorithms is machine dependent, the result from the timing test was used to determine the cut-off point for the Karatsuba algorithm. The program was then modified to include the cut-off value for using each algorithm. (The classical algorithm is better if the digit size is less than 1024.) This then became the final version of the program. Using cout to print the number in hexadecimal did not work correctly in Linux. Therefore, printf was used.

December 15, 2000 Page 10 of 54

Page 11: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

RESULTS To check if the program produce the correct result, the classical and Karatsuba multiplication results were compared. If they are exactly the same, the Karatsuba algorithm is implemented correctly. As a double check, the input values were computed using LiDIA multiplication. The two multiplicands were first converted into decimal before they are multiplied together using the LiDIA multiplication. After that, the Karatsuba multiplication result was converted into decimal and compared with the LiDIA result. If they are exactly the same, the Karatsuba and classical multiplication algorithms are implemented correctly (by the transitive property). A sample of the result is given below: In base 2^16: A = 36113 41803 B = 44944 22839 Classical Multiplication = 24766 39349 36799 10269 Karatsuba Multiplication = 24766 39349 36799 10269 In decimal: A = 2366743371 B = 2945472823 A * B = 6971178278295906333 LiDIA Multiplication = 6971178278295906333 Note the line A * B = 6971178278295906333 was converted from the result of Karatsuba multiplication 24766 39349 36799 10269 (in base 216).

December 15, 2000 Page 11 of 54

Page 12: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

APPENDIX A – Program Test Header File // multiplication.h // header file void get_num(unsigned short a[], unsigned short b[], int size); /* This function will return two integer multiplicands of "size" digits */ void classical_multiplication(unsigned short *a, unsigned short *b, unsigned short *result, int size); /* This function will multiply two number (in array) using classical algorithm The function will return the result of the multiplication in "result" array */ void karatsuba_multiplication(unsigned short *a, unsigned short *b, unsigned short *result, int size); /* This function will multiply two number (in array) using karatsuba algorithm The function will return the result of the multiplication in "result" array Although result requires 6*size space, the product is in the 2*size space */ void lidia_multiplication(unsigned short *a, unsigned short *b, bigint& result, int size); /* This function will multiply two large integers using LiDIA library */ void print_result(unsigned short *a, unsigned short *b, unsigned short *c_result, unsigned short *k_result, bigint l_result, int ize); /* This function will print the output of the multiplication results to screen */ void print_file(unsigned short *a, unsigned short *b, unsigned short *c_result, unsigned short *k_result, bigint l_result, int size, char *file_name); /* This function will print the output of the multiplication results to "file name" on disk */

December 15, 2000 Page 12 of 54

Page 13: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

Implementation File // multiplication.cpp // implementation file #include <iostream.h> #include <math.h> #include <time.h> #include <stdlib.h> #include <LiDIA/bigint.h> #include "multiplication.h" #define DIGIT_SIZE 16 // max # of bits in each digits void get_num(unsigned short a[], unsigned short b[], int size) /* This function will return two integer multiplicands of "size" digits */ { int i; /* Seed the random-number generator with current time so that * the numbers will be different every time we run. */ srand( (unsigned)time( NULL ) ); for (i = 0; i < size; i++) { a[i] = rand() | ((rand()/2) << (DIGIT_SIZE - 1)); // RAND_MAX = 7fff (15 bits) b[i] = rand() | ((rand()/2) << (DIGIT_SIZE - 1)); // but we want 16 bits } // so we OR the most significant with 0 or 1 // set the most significant bit to 1 a[size-1] = a[size-1] | (1 << (DIGIT_SIZE - 1));

b[size-1] = b[size-1] | (1 << (DIGIT_SIZE - 1)); } void split(unsigned int num, unsigned short *a) { // split an unsigned int to 2 unsigned short in an array a[0] = (num << DIGIT_SIZE) >> DIGIT_SIZE; a[1] = num >> DIGIT_SIZE; } void sum_carry(unsigned short *sum, int num, unsigned short *a, int start)

December 15, 2000 Page 13 of 54

Page 14: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

{ // add "sum" list of "num" digits to "a" list of unsigned short int i; unsigned short carry; unsigned int sum1; sum1 = sum[0] + a[start]; a[start] = (sum1 << DIGIT_SIZE) >> DIGIT_SIZE; carry = sum1 >> DIGIT_SIZE; sum1 = a[start+1] + sum[1] + carry; a[start+1] = (sum1 << DIGIT_SIZE) >> DIGIT_SIZE; carry = sum1 >> DIGIT_SIZE; i = 2; while (carry != 0) { sum1 = carry + a[start+i]; a[start+i] = (sum1 << DIGIT_SIZE) >> DIGIT_SIZE; carry = sum1 >> DIGIT_SIZE; i++; } } void subtract_list(unsigned short *a, int a_start, unsigned short *b, int b_start, int length) { // subtract "a" list from "b" list int i; unsigned int num; for (i = 0; i < length; i++) { if (a[a_start+i] <= b[b_start+i]) b[b_start+i] -= a[a_start+i]; else // we have to borrow { num = 0x10000 + b[b_start+i]; b[b_start+i] = num - a[a_start+i]; int j = 1; bool done = false; while ((!done) && (j <= length)) { if (b[b_start+i+j] == 0) b[b_start+i+j] = 0xffff;

December 15, 2000 Page 14 of 54

Page 15: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

else { b[b_start+i+j] -= 1; done = true; } j++; } } } } void add_list(unsigned short *a, int a_start, unsigned short *b, int b_start, int length) { // subtract "a" list from "b" list unsigned int sum; unsigned short result[2]; int i; for (i = 0; i < length; i++) { sum = a[a_start+i] + b[b_start+i]; split(sum, result); b[b_start+i] = 0; sum_carry(result, 2, b, b_start+i); } } void classical_multiplication(unsigned short *a, unsigned short *b, unsigned short *result, int size) /* This function will multiply two number (in array) using classical algorithm The function will return the result of the multiplication in "result" array */ { int i, j; unsigned int product; unsigned short sum[2]; for (i = 0; i < 2 * size; i++) result[i] = 0; for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { product = a[i] * b[j];

December 15, 2000 Page 15 of 54

Page 16: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

split(product, sum); sum_carry(sum, 2, result, i+j); } } } void karatsuba(unsigned short *a, unsigned short *b, unsigned short *result, int size) /* This function will multiply two number (in array) using karatsuba algorithm The function will return the result of the multiplication in "result" array Although result requires 6*size space, the product is in the 2*size space */ { unsigned short *a_low = &a[0]; // low-order half of a unsigned short *a_high = &a[size/2]; // high-order half of a unsigned short *b_low = &b[0]; // low-order half of b unsigned short *b_high = &b[size/2]; // high-order half of b unsigned short *x_low = &result[0 * size]; // product of 2 low unsigned short *x_high = &result[1 * size]; // product of 2 high unsigned short *a_diff = &result[2 * size]; // difference of 2 a's halves unsigned short *b_diff = &result[2 * size + size/2]; // difference of 2 b's halves unsigned short *x_middle = &result[3 * size]; // product of differences of a & b unsigned short *x_diff = &result[4 * size]; // a^2 + b^2 - (product of diff of a & b) bool a_sign = 0; bool b_sign = 0; unsigned int num; int i; if (size == 2) { for (i = 0; i < 6*size; i++) result[i] = 0; num = a_low[0] * b_low[0]; split(num, x_low); num = a_high[0] * b_high[0]; split(num, x_high); if (a_low[size/2-1] > a_high[size/2-1]) a_sign = 1; // positive if (b_low[size/2-1] > b_high[size/2-1]) b_sign = 1; // positive a_diff[0] = abs(a_high[0] - a_low[0]); b_diff[0] = abs(b_low[0] - b_high[0]);

December 15, 2000 Page 16 of 54

Page 17: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

num = a_diff[0] * b_diff[0]; split(num, x_middle); // compute a1*b0 + a0*b1 add_list(x_low, 0, x_diff, 0, size); add_list(x_high, 0, x_diff, 0, size); if (a_sign == b_sign) subtract_list(x_middle, 0, x_diff, 0, size); else add_list(x_middle, 0, x_diff, 0, size); // combine a1*b0 + a0*b1 to result add_list(x_diff, 0, x_low, size/2, 2*size - size/2); } else // For multiplying any 2 numbers of (2^x) digits, we split up into 2 halves { for (i = 0; i < 6*size; i++) result[i] = 0; karatsuba(a_low, b_low, x_low, size/2); for (i = size; i < 6*size; i++) result[i] = 0; karatsuba(a_high, b_high, x_high, size/2); for (i = 2*size; i < 6*size; i++) result[i] = 0; // compute a1 - a0 i = size/2-1; while ((a_low[i] == a_high[i]) && (i != 0)) i--; if (a_low[i] <= a_high[i]) { a_sign = 1; // positive add_list(a_high, 0, a_diff, 0, size/2); subtract_list(a_low, 0, a_diff, 0, size/2); } else { add_list(a_low, 0, a_diff, 0, size/2); subtract_list(a_high, 0, a_diff, 0, size/2); }

December 15, 2000 Page 17 of 54

Page 18: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

// compute b0 - b1 i = size/2-1; while ((b_low[i] == b_high[i]) && (i != 0)) i--; if (b_low[i] >= b_high[i]) { b_sign = 1; // positive add_list(b_low, 0, b_diff, 0, size/2); subtract_list(b_high, 0, b_diff, 0, size/2); } else { add_list(b_high, 0, b_diff, 0, size/2); subtract_list(b_low, 0, b_diff, 0, size/2); } // do recursive calls karatsuba(a_diff, b_diff, x_middle, size/2); for (i = 4*size; i < 6*size; i++) result[i] = 0; // compute a1*b0 + a0*b1 add_list(x_low, 0, x_diff, 0, size); add_list(x_high, 0, x_diff, 0, size); if (a_sign != b_sign) subtract_list(x_middle, 0, x_diff, 0, size); else add_list(x_middle, 0, x_diff, 0, size); // combine recursive calls add_list(x_diff, 0, x_low, size/2, size + size/2); } } void lidia_multiplication(unsigned short *a, unsigned short *b, bigint& result, int size) /* This function will multiply two number (in array) using LiDIA library The function will return the result of the multiplication as a bigint number */ { bigint big_a = 0, big_b = 0, x, y, base = DIGIT_SIZE, radix; int i; for (i = 0; i < size; i++) {

December 15, 2000 Page 18 of 54

Page 19: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

y = base*i; power(radix, 2, y); x = a[i]; big_a += x * radix; x = b[i]; big_b += x * radix; } result = big_a * big_b; } void karatsuba_multiplication(unsigned short *a, unsigned short *b, unsigned short *result, int size) { // initialize any unused digits to 0 int karatsuba_size = int(pow(2, ceil(log(size)/log(2)))); //smallest power of 2 greater than digits for (int i = size; i < karatsuba_size; i++) { a[i] = 0; b[i] = 0; } karatsuba(a, b, result, karatsuba_size); } void print_result(unsigned short *a, unsigned short *b, unsigned short *c_result, unsigned short *k_result, bigint l_result, int size) /* This function will print the output of the multiplication results to screen */ { int i; cout << "\nIn base 2^16:\n\n"; cout << "A = "; for (i = size; i > 0 ; i--) cout << a[i-1] << " "; cout << "\n"; cout << "B = "; for (i = size; i > 0 ; i--) cout << b[i-1] << " "; cout << "\n"; cout << "Classical Multiplication = "; for (i = 2 * size; i > 0; i--) cout << c_result[i-1] << " ";

December 15, 2000 Page 19 of 54

Page 20: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

cout << "\n"; cout << "Karatsuba Multiplication = "; for (i = 2 * size; i > 0; i--) cout << k_result[i-1] << " "; cout << "\n"; cout << "\n\nIn decimal:\n\n"; bigint big_result = 0, big_a = 0, big_b = 0, radix, x, y, z, base=DIGIT_SIZE; for (i = 0; i < size; i++) { x = a[i]; y = b[i]; z = base*i; power(radix, 2, z); big_a += x * radix; big_b += y * radix; } cout << "A = " << big_a << "\n"; cout << "B = " << big_b << "\n"; for (i = 0; i < 2 * size; i++) { y = k_result[i]; z = base*i; power(radix, 2, z); big_result += y * radix; } cout << "A * B = " << big_result << "\n"; cout << "LiDIA Multiplication = " <<l_result << "\n"; } // output.cpp #include <iostream.h> #include <math.h> #include <time.h> #include <stdlib.h> #include <LiDIA/bigint.h> #include <iomanip.h> #include "multiplication.h" #define DIGIT_SIZE 16 // max # of bits in each digit

December 15, 2000 Page 20 of 54

Page 21: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

FILE *stream; void print_file(unsigned short *a, unsigned short *b, unsigned short *c_result, unsigned short *k_result, bigint l_result, int size, char *file_name) /* This function will print the output of the multiplication results to a file */ { int i; stream = fopen(file_name, "a"); fprintf(stream, "A = "); for (i = size; i > 0 ; i--) fprintf(stream, "%04X ", a[i-1]); fprintf(stream, "\n"); fprintf(stream, "B = "); for (i = size; i > 0 ; i--) fprintf(stream, "%04X ", b[i-1]); fprintf(stream, "\n"); fprintf(stream, "Classical Multiplication = "); for (i = 2 * size; i > 0; i--) fprintf(stream, "%04X ", c_result[i-1]); fprintf(stream, "\n"); fprintf(stream, "Karatsuba Multiplication = "); for (i = 2 * size; i > 0; i--) fprintf(stream, "%04X ", k_result[i-1]); fprintf(stream, "\n"); fprintf(stream, "\nIn decimal:\n"); bigint big_result = 0, big_a = 0, big_b = 0, radix, x, y, z, base=DIGIT_SIZE; for (i = 0; i < size; i++) { x = a[i]; y = b[i]; z = base*i; power(radix, 2, z); big_a += x * radix; big_b += y * radix; } fprintf(stream, "A = "); big_a.print_to_file(stream); fprintf(stream, "\n");

December 15, 2000 Page 21 of 54

Page 22: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

fprintf(stream, "B = "); big_b.print_to_file(stream); fprintf(stream, "\n"); for (i = 0; i < 2 * size; i++) { y = k_result[i]; z = base*i; power(radix, 2, z); big_result += y * radix; } fprintf(stream, "A * B = "); big_result.print_to_file(stream); fprintf(stream, "\n"); fprintf(stream, "LiDIA Multiplication = "); l_result.print_to_file(stream); fprintf(stream, "\n"); fprintf(stream, "====================================================================================================\n"); fclose(stream); } void print_result(unsigned short *a, unsigned short *b, unsigned short *c_result, unsigned short *k_result, bigint l_result, int size) /* This function will print the output of the multiplication results to screen */ { int i; printf("A = "); for (i = size; i > 0 ; i--) printf("%04X ", a[i-1]); printf("\n"); printf("B = "); for (i = size; i > 0 ; i--) printf("%04X ", b[i-1]); printf("\n"); printf("Classical Multiplication = "); for (i = 2 * size; i > 0; i--) printf("%04X ", c_result[i-1]); printf("\n");

December 15, 2000 Page 22 of 54

Page 23: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

printf("Karatsuba Multiplication = "); for (i = 2 * size; i > 0; i--) printf("%04X ", k_result[i-1]); printf("\n"); cout << "\n\nIn decimal:\n\n"; bigint big_result = 0, big_a = 0, big_b = 0, radix, x, y, z, base=DIGIT_SIZE; for (i = 0; i < size; i++) { x = a[i]; y = b[i]; z = base*i; power(radix, 2, z); big_a += x * radix; big_b += y * radix; } cout << "A = " << big_a << "\n"; cout << "B = " << big_b << "\n"; for (i = 0; i < 2 * size; i++) { y = k_result[i]; z = base*i; power(radix, 2, z); big_result += y * radix; } cout << "A * B = " << big_result << "\n"; cout << "LiDIA Multiplication = " <<l_result << "\n"; }

December 15, 2000 Page 23 of 54

Page 24: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

Program // project.cpp #include <iostream.h> #include <math.h> #include <time.h> #include <stdlib.h> #include <fstream.h> #include <iomanip.h> #include <bigint.h> #include "multiplication.h" #define MAX_LOOPS 1 #define MAX_DIGITS 15 // max # of MAX_DIGIT in the multiplicants #define DIGIT_SIZE 16 // max # of bits in each mantissa, // also equal to size of unsigned short void main() { const char InputFileName[] = "result.txt"; unsigned short multiplicant1[MAX_DIGITS], multiplicant2[MAX_DIGITS]; unsigned short Classical_result[2*MAX_DIGITS]; unsigned short Karatsuba_result[6*MAX_DIGITS]; bigint LiDIA_result; int digits; /* Seed the random-number generator with current time so that * the numbers will be different every time we run. */ srand( (unsigned int)time(NULL) ); for (digits = 2; digits <= MAX_DIGITS; digits++) { for (int i = 0; i < MAX_LOOPS; i++) { // get the two multiplicants get_num(multiplicant1, multiplicant2, digits); // perform classical multiplication of two numbers of "digits" mantissa classical_multiplication(multiplicant1, multiplicant2, Classical_result, digits); // perform karatsuba multiplication of two numbers of "digits" mantissa karatsuba_multiplication(multiplicant1, multiplicant2, Karatsuba_result, digits); // perform LiDIA multiplication of two numbers of "digits" mantissa

December 15, 2000 Page 24 of 54

Page 25: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

lidia_multiplication(multiplicant1, multiplicant2, LiDIA_result, digits); print_file(multiplicant1, multiplicant2, Classical_result, Karatsuba_result, LiDIA_result, digits, InputFileName); } } }

December 15, 2000 Page 25 of 54

Page 26: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

Result

The result below was obtained from the code ported to Linux. The digits of A, and B are randomly generated. The most significant bit of A and B are set to 1 to ensure that it’s within the range we want. The line A*B is the direct conversion from the result of “Karatsuba Multiplication”. A = F1E6 F07C B = BC5E A2BB Classical Multiplication = B1FF 052C 3568 2294 Karatsuba Multiplication = B1FF 052C 3568 2294 In decimal: A = 4058443900 B = 3160318651 A * B = 12825975951207178900 LiDIA Multiplication = 12825975951207178900 ==================================================================================================== A = D497 CED1 2D3B B = 90AA 8DE6 8310 Classical Multiplication = 7823 06FC 0A7D 3758 193A 04B0 Karatsuba Multiplication = 7823 06FC 0A7D 3758 193A 04B0 In decimal: A = 233748474965307 B = 159062199534352 A * B = 37180546565782145224754726064 LiDIA Multiplication = 37180546565782145224754726064 ==================================================================================================== A = AFEB 7EAC E507 95B5 B = F410 1B5F 1DC2 AC50 Classical Multiplication = A7B7 8643 E84D 3DB3 7195 D0C8 9F1E 6490 Karatsuba Multiplication = A7B7 8643 E84D 3DB3 7195 D0C8 9F1E 6490 In decimal: A = 12676364857206347189 B = 17586586640216927312

December 15, 2000 Page 26 of 54

Page 27: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

A * B = 222933988844260502951673991685048525968 LiDIA Multiplication = 222933988844260502951673991685048525968 ==================================================================================================== A = BFD3 8C89 8D29 A3AB F40A B = A7C6 B147 7FF6 D6B3 E012 Classical Multiplication = 7DB7 E323 4533 559C 9D69 B463 EE33 02FB F69D E8B4 Karatsuba Multiplication = 7DB7 E323 4533 559C 9D69 B463 EE33 02FB F69D E8B4 In decimal: A = 905874388008102049608714 B = 792300432285391442403346 A * B = 717724669215083671634950095690950353527064357044 LiDIA Multiplication = 717724669215083671634950095690950353527064357044 ==================================================================================================== --- other test vector not shown because of limited space --- ==================================================================================================== A = B2AA 815F AF70 9901 2D87 B0FA AA87 717C F04E FDF4 9289 EA48 4AED 4553 D192 B = F022 7E51 560E FAFB A342 AA39 C9E8 B5FA EE47 4574 9047 A490 C874 8AB9 1416 Classical Multiplication = A797 EC17 92DE 9FF8 B467 0C8F 448B CB7B F22C 2614 B866 39CE 9E1D BFB5 D5DF 7A6F FC99 6D2E FCAF 9E75 CBBE 7B90 4384 8950 0000 0000 0000 0000 0000 0000 Karatsuba Multiplication = A797 EC17 92DE 9FF8 B467 0C8F 448B CB7B F22C 2614 B866 39CE 9E1D BFB5 D5DF 7A6F FC99 6D2E FCAF 9E75 CBBE 7B90 4384 8950 A5E1 E75C 24BC 4881 A815 6A8C In decimal: A = 1233107665310415387985793898077138252149173146255005123799685181646033298 B = 1657349064224926660012145186133196234976885425501729918967695623333680150 A * B = 2043689835190801001323098280824771271905733540955197566151244648431601372541140583259419891075909185972264282455831568647883443151280291781634700 LiDIA Multiplication = 2043689835190801001323098280824771271905733540955197566151244648431601372541140583259419891075909185972264282455831568647883443151280291781634700 ====================================================================================================

December 15, 2000 Page 27 of 54

Page 28: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

APPENDIX B - Timing Test Header File for the Timing Test // multiplication.h // header file void get_num(unsigned short a[], unsigned short b[], int size); /* This function will return two integer multiplicands of "size" digits */ void classical_multiplication(unsigned short *a, unsigned short *b, unsigned short *result, int size); /* This function will multiply two number (in array) using classical algorithm The function will return the result of the multiplication in "result" array */ void karatsuba_multiplication(unsigned short *a, unsigned short *b, unsigned short *result, int size); /* This function will multiply two number (in array) using karatsuba algorithm The function will return the result of the multiplication in "result" array Although result requires 6*size space, the product is in the 2*size space */

December 15, 2000 Page 28 of 54

Page 29: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

Implementation File for the Timing Test // multiplication.cpp // implementation file #include <iostream.h> #include <math.h> #include <time.h> #include <stdlib.h> #include "multiplication.h" #define DIGIT_SIZE 16 // max # of bits in each digit void get_num(unsigned short a[], unsigned short b[], int size) /* This function will return two integer multiplicands of "size" digits */ { int i; for (i = 0; i < size; i++) { a[i] = rand() | ((rand()/2) << (DIGIT_SIZE - 1)); // RAND_MAX = 7fff (15 bits) b[i] = rand() | ((rand()/2) << (DIGIT_SIZE - 1)); // but we want 16 bits } // so we OR the most significant with 0 or 1 // set the most significant bit to 1 a[size-1] = a[size-1] | (1 << (DIGIT_SIZE - 1)); b[size-1] = b[size-1] | (1 << (DIGIT_SIZE - 1)); } void split(unsigned int num, unsigned short *a) { // split an unsigned int to 2 unsigned short in an array a[0] = (num << DIGIT_SIZE) >> DIGIT_SIZE; a[1] = num >> DIGIT_SIZE; } void sum_carry(unsigned short *sum, int num, unsigned short *a, int start) { // add "sum" list of "num" digits to "a" list of unsigned short int i; unsigned short carry; unsigned int sum1;

December 15, 2000 Page 29 of 54

Page 30: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

sum1 = sum[0] + a[start]; a[start] = (sum1 << DIGIT_SIZE) >> DIGIT_SIZE; carry = sum1 >> DIGIT_SIZE; sum1 = a[start+1] + sum[1] + carry; a[start+1] = (sum1 << DIGIT_SIZE) >> DIGIT_SIZE; carry = sum1 >> DIGIT_SIZE; i = 2; while (carry != 0) { sum1 = carry + a[start+i]; a[start+i] = (sum1 << DIGIT_SIZE) >> DIGIT_SIZE; carry = sum1 >> DIGIT_SIZE; i++; } } void subtract_list(unsigned short *a, int a_start, unsigned short *b, int b_start, int length) { // subtract "a" list from "b" list int i; unsigned int num; for (i = 0; i < length; i++) { if (a[a_start+i] <= b[b_start+i]) b[b_start+i] -= a[a_start+i]; else // we have to borrow { num = 0x10000 + b[b_start+i]; b[b_start+i] = num - a[a_start+i]; int j = 1; bool done = false; while ((!done) && (j <= length)) { if (b[b_start+i+j] == 0) b[b_start+i+j] = 0xffff; else { b[b_start+i+j] -= 1; done = true; }

December 15, 2000 Page 30 of 54

Page 31: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

j++; } } } } void add_list(unsigned short *a, int a_start, unsigned short *b, int b_start, int length) { // subtract "a" list from "b" list unsigned int sum; unsigned short result[2]; int i; for (i = 0; i < length; i++) { sum = a[a_start+i] + b[b_start+i]; split(sum, result); b[b_start+i] = 0; sum_carry(result, 2, b, b_start+i); } } void classical_multiplication(unsigned short *a, unsigned short *b, unsigned short *result, int size) /* This function will multiply two number (in array) using classical algorithm The function will return the result of the multiplication in "result" array */ { int i, j; unsigned int product; unsigned short sum[2]; for (i = 0; i < 2 * size; i++) result[i] = 0; for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { product = a[i] * b[j]; split(product, sum); sum_carry(sum, 2, result, i+j); } } }

December 15, 2000 Page 31 of 54

Page 32: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

void karatsuba(unsigned short *a, unsigned short *b, unsigned short *result, int size) /* This function will multiply two number (in array) using karatsuba algorithm The function will return the result of the multiplication in "result" array Although result requires 6*size space, the product is in the 2*size space */ { unsigned short *a_low = &a[0]; // low-order half of a unsigned short *a_high = &a[size/2]; // high-order half of a unsigned short *b_low = &b[0]; // low-order half of b unsigned short *b_high = &b[size/2]; // high-order half of b unsigned short *x_low = &result[0 * size]; // product of 2 low unsigned short *x_high = &result[1 * size]; // product of 2 high unsigned short *a_diff = &result[2 * size]; // difference of 2 a's halves unsigned short *b_diff = &result[2 * size + size/2]; // difference of 2 b's halves unsigned short *x_middle = &result[3 * size]; // product of differences of a & b unsigned short *x_diff = &result[4 * size]; // a^2 + b^2 - (product of diff of a & b) bool a_sign = 0; bool b_sign = 0; unsigned int num; int i; if (size == 2) { for (i = 0; i < 6*size; i++) result[i] = 0; num = a_low[0] * b_low[0]; split(num, x_low); num = a_high[0] * b_high[0]; split(num, x_high); if (a_low[size/2-1] > a_high[size/2-1]) a_sign = 1; // positive if (b_low[size/2-1] > b_high[size/2-1]) b_sign = 1; // positive a_diff[0] = abs(a_high[0] - a_low[0]); b_diff[0] = abs(b_low[0] - b_high[0]); num = a_diff[0] * b_diff[0]; split(num, x_middle); // compute a1*b0 + a0*b1 add_list(x_low, 0, x_diff, 0, size);

December 15, 2000 Page 32 of 54

Page 33: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

add_list(x_high, 0, x_diff, 0, size); if (a_sign == b_sign) subtract_list(x_middle, 0, x_diff, 0, size); else add_list(x_middle, 0, x_diff, 0, size); // combine a1*b0 + a0*b1 to result add_list(x_diff, 0, x_low, size/2, 2*size - size/2); } else // For multiplying any 2 numbers of (2^x) digits, we split up into 2 halves { for (i = 0; i < 6*size; i++) result[i] = 0; karatsuba(a_low, b_low, x_low, size/2); for (i = size; i < 6*size; i++) result[i] = 0; karatsuba(a_high, b_high, x_high, size/2); for (i = 2*size; i < 6*size; i++) result[i] = 0; // compute a1 - a0 i = size/2-1; while ((a_low[i] == a_high[i]) && (i != 0)) i--; if (a_low[i] <= a_high[i]) { a_sign = 1; // positive add_list(a_high, 0, a_diff, 0, size/2); subtract_list(a_low, 0, a_diff, 0, size/2); } else { add_list(a_low, 0, a_diff, 0, size/2); subtract_list(a_high, 0, a_diff, 0, size/2); } // compute b0 - b1 i = size/2-1; while ((b_low[i] == b_high[i]) && (i != 0)) i--; if (b_low[i] >= b_high[i])

December 15, 2000 Page 33 of 54

Page 34: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

{ b_sign = 1; // positive add_list(b_low, 0, b_diff, 0, size/2); subtract_list(b_high, 0, b_diff, 0, size/2); } else { add_list(b_high, 0, b_diff, 0, size/2); subtract_list(b_low, 0, b_diff, 0, size/2); } // do recursive calls karatsuba(a_diff, b_diff, x_middle, size/2); for (i = 4*size; i < 6*size; i++) result[i] = 0; // compute a1*b0 + a0*b1 add_list(x_low, 0, x_diff, 0, size); add_list(x_high, 0, x_diff, 0, size); if (a_sign != b_sign) subtract_list(x_middle, 0, x_diff, 0, size); else add_list(x_middle, 0, x_diff, 0, size); // combine recursive calls add_list(x_diff, 0, x_low, size/2, size + size/2); } } void karatsuba_multiplication(unsigned short *a, unsigned short *b, unsigned short *result, int size) { // initialize any unused digits to 0 int karatsuba_size = int(pow(2, ceil(log(size)/log(2)))); //smallest power of 2 greater than digits for (int i = size; i < karatsuba_size; i++) { a[i] = 0; b[i] = 0; } karatsuba(a, b, result, karatsuba_size); }

December 15, 2000 Page 34 of 54

Page 35: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

Timing Test Program // project.cpp // compute time cycle using by classical and karatsuba multiplication // this methodology is based on the NIST's Efficiency Test of the AES algorithm contest #include <iostream.h> #include <stdlib.h> #include <math.h> #include <string.h> #include <fstream.h> #include <time.h> #include <iomanip.h> #include "multiplication.h" #define MAX_LOOPS 100000 #define MAX_DIGITS 16 // max # of MAX_DIGITS in the multiplicants #define DIGIT_SIZE 16 // max # of bits in each digits, // also equal to size of unsigned short void processData(int); double StDev(int ind, double med); double Median(int ind); double AvgIf(int ind, double dev, double med); void total_time(int); double data[MAX_LOOPS][2]; int num_loops = MAX_LOOPS; fstream Outstream("clock.txt", ios::app); fstream TotalStream("total_clock.txt", ios::app); void main() { unsigned short multiplicant1[MAX_DIGITS], multiplicant2[MAX_DIGITS]; unsigned short Classical_result[2*MAX_DIGITS]; unsigned short Karatsuba_result[6*MAX_DIGITS]; clock_t start, finish; int i, digits; /* Seed the random-number generator with current time so that * the numbers will be different every time we run. */ srand( (unsigned int)time(NULL) );

December 15, 2000 Page 35 of 54

Page 36: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

Outstream << "Average Cycle Time with " << num_loops << " iterations (in seconds)\n\n"; Outstream << setw(10) << "# Digits" << setw(30) << "Classical Multiplication" << setw(30) << "Karatsuba Mulltiplication" << "\n\n"; Outstream << setiosflags( ios::fixed ); TotalStream << "Total Time with " << num_loops << " iterations (in seconds)\n\n"; TotalStream << setw(10) << "# Digits" << setw(30) << "Classical Multiplication" << setw(30) << "Karatsuba Mulltiplication" << "\n\n"; TotalStream << setiosflags( ios::fixed ); for ( digits=2; digits<=MAX_DIGITS; digits *= 2) { for ( i=0; i<num_loops; i++ ) { get_num(multiplicant1, multiplicant2, digits); __asm { cli; // clear interrupt flag } start = clock(); // perform classical multiplication of two numbers of "digits" digits classical_multiplication(multiplicant1, multiplicant2, Classical_result, digits); finish = clock(); data[i][0] = double (finish-start)/CLOCKS_PER_SEC; start = clock(); // perform karatsuba multiplication of two numbers of "digits" digits karatsuba_multiplication(multiplicant1, multiplicant2, Karatsuba_result, digits); finish = clock(); data[i][1] = double (finish-start)/CLOCKS_PER_SEC; __asm { sti; //set interrupt flag } } processData(digits); total_time(digits); } }

December 15, 2000 Page 36 of 54

Page 37: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

void processData(int digit) { int ind; double dev; double med; double avg[2]; for ( ind=0; ind<2; ind++ ) { med = Median(ind); dev = StDev(ind, med); avg[ind] = AvgIf(ind, dev*3, med); } Outstream << setw(10) << digit << setw(30) << avg[0] << setw(30)<< avg[1] << setw(30) << "\n"; } double StDev(int ind, double med) { double sum = 0.0, dev, scale; int i, count=0; scale = (1.0 * med)/10000.0; for ( i=0; i<num_loops; i++ ) { /* throw out outliers */ if ( data[i][ind] > 2*med ) break; sum += (data[i][ind]/scale - med/scale)*(data[i][ind]/scale - med/scale); count++; } dev = sqrt(sum/(count-1)); dev = dev * scale; return (dev); } double Median(int ind) { int i, j; double temp; for ( i=0; i<num_loops/2+1; i++ ) for ( j=i; j<num_loops; j++ ) if ( data[i][ind] > data[j][ind] ) { temp = data[j][ind]; data[j][ind] = data[i][ind]; data[i][ind] = temp; } return (data[i-1][ind]); }

December 15, 2000 Page 37 of 54

Page 38: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

double AvgIf(int ind, double dev, double med) { int i, count = 0; double total = 0; for ( i=0; i<num_loops; i++ ) if ( abs(data[i][ind] - med) <= dev ) { total += data[i][ind]; count++; } if ( count == 0 ) return (0); else return (total/count); } void total_time(int digit) { int i, count = 0; double total[2]; total[0] = 0; total[1] = 0; for ( i=0; i<num_loops; i++ ) { total[0] += data[i][0]; total[1] += data[i][1]; } TotalStream << setw(10) << digit << setw(30) << total[0] << setw(30)<< total[1] << "\n"; }

December 15, 2000 Page 38 of 54

Page 39: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

Timing Test Table IBM ThinkPad, 600MHz, 128MB RAM – MS Windows98, MS Visual C++ 6.0 Average Clock Time with 1000 iterations (in seconds)

December 15, 2000 Page 39 of 54

Page 40: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

IBM ThinkPad, 600MHz, 128MB RAM – MS Windows98, MS Visual C++ 6.0 Average Clock Time with 1000 iterations (in seconds)

December 15, 2000 Page 40 of 54

Page 41: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

APPENDIX C - Cycle Count Test Header File for the Cycle Count Test

The same header file for the Timing Test was used. See Appendix B. Implementation File for Cycle Count Test

The same header file for the Timing Test was used. See Appendix B.

December 15, 2000 Page 41 of 54

Page 42: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

Cycle Count Test Program // project.cpp // compute clock cycles used by classical and karatsuba multiplication #include <iostream.h> #include <stdlib.h> #include <math.h> #include <string.h> #include <fstream.h> #include <iomanip.h> #include "multiplication.h" unsigned int CPUID = 0xa20f; // to clear instruction cache unsigned int RDTSC = 0x310f; // to read time stamp counter #define MAX_LOOPS 1000 unsigned int TimeClassical(unsigned short *a, unsigned short *b, unsigned short *result, int size); unsigned int TimeKaratsuba(unsigned short *a, unsigned short *b, unsigned short *result, int size); void processData(int); double StDev(int ind, double med); double Median(int ind); double AvgIf(int ind, double dev, double med); double data[MAX_LOOPS][2]; int num_loops = MAX_LOOPS; const int MAX_DIGITS = 2048; // max # of MAX_DIGITS in the multiplicants fstream Outstream("cycle.txt", ios::out); void main() { int i; unsigned short multiplicant1[MAX_DIGITS], multiplicant2[MAX_DIGITS]; unsigned short classical_result[2*MAX_DIGITS]; unsigned short karatsuba_result[6*MAX_DIGITS]; int digits; unsigned int base=0; unsigned int cyc; __asm {

December 15, 2000 Page 42 of 54

Page 43: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

pushad CPUID RDTSC mov cyc, eax popad pushad CPUID RDTSC sub eax, cyc mov base, eax popad pushad CPUID RDTSC mov cyc, eax popad pushad CPUID RDTSC sub eax, cyc mov base, eax popad pushad CPUID RDTSC mov cyc, eax popad pushad CPUID RDTSC sub eax, cyc mov base, eax popad } Outstream << "Average Cycle Time with " << num_loops << " iterations (in " << MAX_LOOPS << "'s)\n\n"; Outstream << setw(10) << "# digits" << setw(30) << "Classical Multiplication" << setw(30) << "Karatsuba Multiplication" << "\n\n"; Outstream << setiosflags( ios::fixed ); for ( digits=2; digits<=MAX_DIGITS; digits *= 2) { for ( i=0; i<num_loops; i++ ) { get_num(multiplicant1, multiplicant2, digits);

December 15, 2000 Page 43 of 54

Page 44: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

// we are dividing by max_loops so it doesn't overflow data[i][0] = (TimeClassical(multiplicant1, multiplicant2, classical_result, digits)-base)/MAX_LOOPS; data[i][1] = (TimeKaratsuba(multiplicant1, multiplicant2, karatsuba_result, digits)-base)/MAX_LOOPS; } processData(digits); } } unsigned int TimeClassical(unsigned short *a, unsigned short *b, unsigned short *result, int size) { unsigned int cycles; __asm { cli; // clear interrupt flag pushad CPUID RDTSC mov cycles, eax popad } classical_multiplication(a, b, result, size); __asm { pushad CPUID RDTSC sub eax, cycles mov cycles, eax popad sti; //set interrupt flag } return cycles; } unsigned int TimeKaratsuba(unsigned short *a, unsigned short *b, unsigned short *result, int size) { unsigned int cycles; __asm { cli; // clear interrupt flag pushad CPUID RDTSC

December 15, 2000 Page 44 of 54

Page 45: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

mov cycles, eax popad } karatsuba_multiplication(a, b, result, size); __asm { pushad CPUID RDTSC sub eax, cycles mov cycles, eax popad sti; //set interrupt flag } return cycles; } void processData(int digit) { int ind; double dev; double med; double avg[2]; for ( ind=0; ind<2; ind++ ) { med = Median(ind); dev = StDev(ind, med); avg[ind] = AvgIf(ind, dev*3, med); } Outstream << setw(10) << digit << setw(30) << avg[0] << setw(30)<< avg[1] << "\n"; } double StDev(int ind, double med) { double sum = 0.0, dev, scale; int i, count=0; scale = (1.0 * med)/10000.0; for ( i=0; i<num_loops; i++ ) { /* throw out outliers */ if ( data[i][ind] > 2*med ) break; sum += (data[i][ind]/scale - med/scale)*(data[i][ind]/scale - med/scale); count++;

December 15, 2000 Page 45 of 54

Page 46: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

} dev = sqrt(sum/(count-1)); dev = dev * scale; return (dev); } double Median(int ind) { int i, j; double temp; for ( i=0; i<num_loops/2+1; i++ ) for ( j=i; j<num_loops; j++ ) if ( data[i][ind] > data[j][ind] ) { temp = data[j][ind]; data[j][ind] = data[i][ind]; data[i][ind] = temp; } return (data[i-1][ind]); } double AvgIf(int ind, double dev, double med) { int i, count = 0; double total = 0; for ( i=0; i<num_loops; i++ ) if ( abs(data[i][ind] - med) <= dev ) { total += data[i][ind]; count++; } if ( count == 0 ) return (0); else return (total/count); }

December 15, 2000 Page 46 of 54

Page 47: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

Cycle Counts Table IBM ThinkPad, 600MHz, 128MB RAM – MS Windows98, MS Visual C++ 6.0 Average Cycle Time with 1000 iterations (in 1000's)

December 15, 2000 Page 47 of 54

Page 48: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

IBM ThinkPad, 600MHz, 128MB RAM – MS Windows98, MS Visual C++ 6.0 Average Cycle Time with 1000 iterations (in 1000's)

December 15, 2000 Page 48 of 54

Page 49: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

APPENDIX D – Final Implementation of Two Equal Digit Size Large Numbers // multiplication.cpp // implementation file #include <iostream.h> #include <math.h> #include <time.h> #include <stdlib.h> #include "multiplication.h" #define DIGIT_SIZE 16 // max # of bits in each digit void get_num(unsigned short a[], unsigned short b[], int size) /* This function will return two integer multiplicands of "size" digits */ { int i; for (i = 0; i < size; i++) { a[i] = rand() | ((rand()/2) << (DIGIT_SIZE - 1)); // RAND_MAX = 7fff (15 bits) b[i] = rand() | ((rand()/2) << (DIGIT_SIZE - 1)); // but we want 16 bits } // so we OR the most significant with 0 or 1 // set the most significant bit to 1 a[size-1] = a[size-1] | (1 << (DIGIT_SIZE - 1)); b[size-1] = b[size-1] | (1 << (DIGIT_SIZE - 1)); } void split(unsigned int num, unsigned short *a) { // split an unsigned int to 2 unsigned short in an array a[0] = (num << DIGIT_SIZE) >> DIGIT_SIZE; a[1] = num >> DIGIT_SIZE; } void sum_carry(unsigned short *sum, int num, unsigned short *a, int start) { // add "sum" list of "num" digits to "a" list of unsigned short int i; unsigned short carry; unsigned int sum1;

December 15, 2000 Page 49 of 54

Page 50: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

sum1 = sum[0] + a[start]; a[start] = (sum1 << DIGIT_SIZE) >> DIGIT_SIZE; carry = sum1 >> DIGIT_SIZE; sum1 = a[start+1] + sum[1] + carry; a[start+1] = (sum1 << DIGIT_SIZE) >> DIGIT_SIZE; carry = sum1 >> DIGIT_SIZE; i = 2; while (carry != 0) { sum1 = carry + a[start+i]; a[start+i] = (sum1 << DIGIT_SIZE) >> DIGIT_SIZE; carry = sum1 >> DIGIT_SIZE; i++; } } void subtract_list(unsigned short *a, int a_start, unsigned short *b, int b_start, int length) { // subtract "a" list from "b" list int i; unsigned int num; for (i = 0; i < length; i++) { if (a[a_start+i] <= b[b_start+i]) b[b_start+i] -= a[a_start+i]; else // we have to borrow { num = 0x10000 + b[b_start+i]; b[b_start+i] = num - a[a_start+i]; int j = 1; bool done = false; while ((!done) && (j <= length)) { if (b[b_start+i+j] == 0) b[b_start+i+j] = 0xffff; else { b[b_start+i+j] -= 1; done = true; }

December 15, 2000 Page 50 of 54

Page 51: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

j++; } } } } void add_list(unsigned short *a, int a_start, unsigned short *b, int b_start, int length) { // subtract "a" list from "b" list unsigned int sum; unsigned short result[2]; int i; for (i = 0; i < length; i++) { sum = a[a_start+i] + b[b_start+i]; split(sum, result); b[b_start+i] = 0; sum_carry(result, 2, b, b_start+i); } } void classical_multiplication(unsigned short *a, unsigned short *b, unsigned short *result, int size) /* This function will multiply two number (in array) using classical algorithm The function will return the result of the multiplication in "result" array */ { int i, j; unsigned int product; unsigned short sum[2]; for (i = 0; i < 2 * size; i++) result[i] = 0; for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { product = a[i] * b[j]; split(product, sum); sum_carry(sum, 2, result, i+j); } } }

December 15, 2000 Page 51 of 54

Page 52: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

void karatsuba(unsigned short *a, unsigned short *b, unsigned short *result, int size) /* This function will multiply two number (in array) using karatsuba algorithm The function will return the result of the multiplication in "result" array Although result requires 6*size space, the product is in the 2*size space */ { unsigned short *a_low = &a[0]; // low-order half of a unsigned short *a_high = &a[size/2]; // high-order half of a unsigned short *b_low = &b[0]; // low-order half of b unsigned short *b_high = &b[size/2]; // high-order half of b unsigned short *x_low = &result[0 * size]; // product of 2 low unsigned short *x_high = &result[1 * size]; // product of 2 high unsigned short *a_diff = &result[2 * size]; // difference of 2 a's halves unsigned short *b_diff = &result[2 * size + size/2]; // difference of 2 b's halves unsigned short *x_middle = &result[3 * size]; // product of differences of a & b unsigned short *x_diff = &result[4 * size]; // a^2 + b^2 - (product of diff of a & b) bool a_sign = 0; bool b_sign = 0; unsigned int num; int i; if (size == 2) { classical(a, b, result, size); } else // For multiplying any 2 numbers of (2^x) digits, we split up into 2 halves { for (i = 0; i < 6*size; i++) result[i] = 0; karatsuba(a_low, b_low, x_low, size/2); for (i = size; i < 6*size; i++) result[i] = 0; karatsuba(a_high, b_high, x_high, size/2); for (i = 2*size; i < 6*size; i++) result[i] = 0; // compute a1 - a0 i = size/2-1; while ((a_low[i] == a_high[i]) && (i != 0))

December 15, 2000 Page 52 of 54

Page 53: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

i--; if (a_low[i] <= a_high[i]) { a_sign = 1; // positive add_list(a_high, 0, a_diff, 0, size/2); subtract_list(a_low, 0, a_diff, 0, size/2); } else { add_list(a_low, 0, a_diff, 0, size/2); subtract_list(a_high, 0, a_diff, 0, size/2); } // compute b0 - b1 i = size/2-1; while ((b_low[i] == b_high[i]) && (i != 0)) i--; if (b_low[i] >= b_high[i]) { b_sign = 1; // positive add_list(b_low, 0, b_diff, 0, size/2); subtract_list(b_high, 0, b_diff, 0, size/2); } else { add_list(b_high, 0, b_diff, 0, size/2); subtract_list(b_low, 0, b_diff, 0, size/2); } // do recursive calls karatsuba(a_diff, b_diff, x_middle, size/2); for (i = 4*size; i < 6*size; i++) result[i] = 0; // compute a1*b0 + a0*b1 add_list(x_low, 0, x_diff, 0, size); add_list(x_high, 0, x_diff, 0, size); if (a_sign != b_sign) subtract_list(x_middle, 0, x_diff, 0, size); else add_list(x_middle, 0, x_diff, 0, size); // combine recursive calls add_list(x_diff, 0, x_low, size/2, size + size/2); } }

December 15, 2000 Page 53 of 54

Page 54: Software Implementation of Classical and Karatsuba ...€¦ · Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do INTRODUCTION Background The basic

Multiplication of large integers using Karatsuba and classical algorithms Thanh V. Do

void karatsuba_multiplication(unsigned short *a, unsigned short *b, unsigned short *result, int size) { // initialize any unused digits to 0 int karatsuba_size = int(pow(2, ceil(log(size)/log(2)))); //smallest power of 2 greater than digits for (int i = size; i < karatsuba_size; i++) { a[i] = 0; b[i] = 0; } karatsuba(a, b, result, karatsuba_size); }

December 15, 2000 Page 54 of 54


Recommended