using System.Diagnostics; namespace Lab_5 { public class Program { //Sequential multiplication of two polynomials //O(n^2) public static List PolynomialMultiplication(List poly1, List poly2) { int m = poly1.Count; int n = poly2.Count; List result = new List(new int[m + n - 1]); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { result[i + j] += poly1[i] * poly2[j]; } } return result; } //Karatsuba algorithm for polynomial multiplication public static List AddPolynomials(List poly1, List poly2) { int maxLength = Math.Max(poly1.Count, poly2.Count); List result = new List(new int[maxLength]); for (int i = 0; i < maxLength; i++) { int coef1 = i < poly1.Count ? poly1[i] : 0; int coef2 = i < poly2.Count ? poly2[i] : 0; result[i] = coef1 + coef2; } return result; } public static List SubtractPolynomials(List poly1, List poly2) { int maxLength = Math.Max(poly1.Count, poly2.Count); List result = new List(new int[maxLength]); for (int i = 0; i < maxLength; i++) { int coef1 = i < poly1.Count ? poly1[i] : 0; int coef2 = i < poly2.Count ? poly2[i] : 0; result[i] = coef1 - coef2; } return result; } public static List Karatsuba(List poly1, List poly2) { int n = Math.Max(poly1.Count, poly2.Count); if (n == 1) { return new List { poly1[0] * poly2[0] }; } while (poly1.Count < n) poly1.Add(0); while (poly2.Count < n) poly2.Add(0); int half = n / 2; List low1 = poly1.GetRange(0, half); List high1 = poly1.GetRange(half, n - half); List low2 = poly2.GetRange(0, half); List high2 = poly2.GetRange(half, n - half); List z0 = Karatsuba(low1, low2); List z1 = Karatsuba(AddPolynomials(low1, high1), AddPolynomials(low2, high2)); List z2 = Karatsuba(high1, high2); List result = new List(new int[2 * n - 1]); for (int i = 0; i < z0.Count; i++) result[i] += z0[i]; List middle = SubtractPolynomials(SubtractPolynomials(z1, z0), z2); for (int i = 0; i < middle.Count; i++) result[i + half] += middle[i]; for (int i = 0; i < z2.Count; i++) result[i + 2 * half] += z2[i]; return result; } //Parallel multiplication of two polynomials //O(n^2) public static List ParallelPolynomialMultiplication(List poly1, List poly2) { int m = poly1.Count; int n = poly2.Count; List result = new List(new int[m + n - 1]); Parallel.For(0, m, i => { for (int j = 0; j < n; j++) { result[i + j] += poly1[i] * poly2[j]; } }); return result; } //Karatsuba algorithm for polynomial multiplication public static List ParallelKaratsuba(List poly1, List poly2) { int n = Math.Max(poly1.Count, poly2.Count); if (n == 1) { return new List { poly1[0] * poly2[0] }; } while (poly1.Count < n) poly1.Add(0); while (poly2.Count < n) poly2.Add(0); int half = n / 2; List low1 = poly1.GetRange(0, half); List high1 = poly1.GetRange(half, n - half); List low2 = poly2.GetRange(0, half); List high2 = poly2.GetRange(half, n - half); List z0 = [], z1 = [], z2 = []; Parallel.Invoke( () => z0 = ParallelKaratsuba(low1, low2), () => z1 = ParallelKaratsuba(AddPolynomials(low1, high1), AddPolynomials(low2, high2)), () => z2 = ParallelKaratsuba(high1, high2) ); List result = new List(new int[2 * n - 1]); for (int i = 0; i < z0.Count; i++) result[i] += z0[i]; List middle = SubtractPolynomials(SubtractPolynomials(z1, z0), z2); for (int i = 0; i < middle.Count; i++) result[i + half] += middle[i]; for (int i = 0; i < z2.Count; i++) result[i + 2 * half] += z2[i]; return result; } public static void Main(string[] args) { int degree = 999; Random random = new Random(); // Generate Polynomial 1 List poly1 = new List(); for (int i = 0; i <= degree; i++) { poly1.Add(random.Next(-100, 101)); } // Generate Polynomial 2 List poly2 = new List(); for (int i = 0; i <= degree; i++) { poly2.Add(random.Next(-100, 101)); } //Console.WriteLine("Polynomial 1: " + string.Join(" ", poly1)); //Console.WriteLine("Polynomial 2: " + string.Join(" ", poly2)); Stopwatch timer = new Stopwatch(); timer.Start(); List result = PolynomialMultiplication(poly1, poly2); timer.Stop(); //Console.WriteLine("Result O(n) sequencial: " + string.Join(" ", result)); Console.WriteLine("Time: " + timer.ElapsedMilliseconds + "ms"); timer.Start(); result = Karatsuba(poly1, poly2); timer.Stop(); //Console.WriteLine("Result Karatsuba sequencial: " + string.Join(" ", result)); Console.WriteLine("Time: " + timer.ElapsedMilliseconds + "ms"); timer.Start(); result = ParallelPolynomialMultiplication(poly1, poly2); timer.Stop(); //Console.WriteLine("Result O(n) parallel: " + string.Join(" ", result)); Console.WriteLine("Time: " + timer.ElapsedMilliseconds + "ms"); timer.Start(); result = ParallelKaratsuba(poly1, poly2); timer.Stop(); //Console.WriteLine("Result Karatsuba parallel: " + string.Join(" ", result)); Console.WriteLine("Time: " + timer.ElapsedMilliseconds + "ms"); } } }