public static BigNumber AddParallel(params BigNumber[] numbers) { if (numbers.Length <= 1) { throw new InvalidOperationException("Array too small!"); } var first = numbers[0]; var firstQueue = new BigNumberQueue(); for (var i = 0; i < first.Digits.Length; ++i) { firstQueue.Enqueue(new Tuple <int, int>(i, first.Digits[i])); } firstQueue.Done = true; var queues = new BigNumberQueue[numbers.Length]; queues[0] = firstQueue; for (var i = 1; i < numbers.Length; ++i) { queues[i] = AddParallel(queues[i - 1], numbers[i]); } while (!queues[numbers.Length - 1].Done) { } var result = new List <int>(); while (queues[numbers.Length - 1].Count > 0) { result.Add(queues[numbers.Length - 1].Dequeue().Item2); } result.Reverse(); return(new BigNumber(result.ToArray())); }
private static BigNumberQueue AddParallel(BigNumberQueue a, BigNumber b) { var result = new BigNumberQueue(); Task.Factory.StartNew(() => { var transport = 0; int i; for (i = 0; i < b.Digits.Length; ++i) { while (!a.Done && (a.Count == 0)) // Waiting for a digit. { } if (a.Done && (a.Count == 0)) // Finished all digits from "a", just adding "b". { lock (result) { result.Enqueue(new Tuple <int, int>(i, (transport + b.Digits[i]) % 10)); transport = (transport + b.Digits[i]) / 10; } } if (a.Count > 0) // We have a digit from a previous computation. { lock (a) { var digit = a.Dequeue(); if (digit.Item1 != i) { throw new InvalidOperationException("Out of order!"); } lock (result) { result.Enqueue(new Tuple <int, int>(i, (transport + digit.Item2 + b.Digits[i]) % 10)); transport = (transport + digit.Item2 + b.Digits[i]) / 10; } } } } while (!(a.Done && (a.Count == 0))) // Finished all digits from "b", just adding "a". { if (a.Count > 0) { lock (a) { var digit = a.Dequeue(); lock (result) { result.Enqueue(new Tuple <int, int>(i, (transport + digit.Item2) % 10)); transport = (transport + digit.Item2) / 10; i++; } } } } if (transport > 0) // We can have at most one extra digit in the transport variable. { lock (result) { result.Enqueue(new Tuple <int, int>(i, transport)); } } result.Done = true; // Signal that we have finished the computations. }); return(result); }