Beispiel #1
0
        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()));
        }
Beispiel #2
0
        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);
        }