private static UncertainValue Integrate_Adaptive(MultiFunctor f, CoordinateTransform[] map, IntegrationRegion r, EvaluationSettings settings)
        {
            // Create an evaluation rule
            GenzMalik75Rule rule = new GenzMalik75Rule(r.Dimension);

            // Use it on the whole region and put the answer in a linked list
            rule.Evaluate(f, map, r);
            LinkedList<IntegrationRegion> regionList = new LinkedList<IntegrationRegion>();
            regionList.AddFirst(r);

            // Iterate until convergence
            while (f.EvaluationCount < settings.EvaluationBudget) {

                // Add up value and errors in all regions.
                // While we are at it, take note of the region with the largest error.
                double value = 0.0;
                double error = 0.0;
                LinkedListNode<IntegrationRegion> regionNode = regionList.First;
                double maxError = 0.0;
                LinkedListNode<IntegrationRegion> maxErrorNode = null;
                while (regionNode != null) {
                    IntegrationRegion region = regionNode.Value;
                    value += region.Value;
                    error += region.Error;
                    //error += MoreMath.Sqr(region.Error);
                    if (region.Error > maxError) {
                        maxError = region.Error;
                        maxErrorNode = regionNode;
                    }
                    regionNode = regionNode.Next;
                }

                // Check for convergence.
                if ((error <= settings.AbsolutePrecision) || (error <= settings.RelativePrecision * Math.Abs(value))) {
                    return (new UncertainValue(value, error));
                }

                // Split the region with the largest error, and evaluate each subregion.
                IntegrationRegion maxErrorRegion = maxErrorNode.Value;
                regionList.Remove(maxErrorNode);
                IList<IntegrationRegion> subRegions = maxErrorRegion.Split(maxErrorRegion.SplitIndex);
                /*
                Countdown cnt = new Countdown(2);
                ThreadPool.QueueUserWorkItem((object state) => { rule.Evaluate(f, subRegions[0]); cnt.Signal(); });
                ThreadPool.QueueUserWorkItem((object state) => { rule.Evaluate(f, subRegions[1]); cnt.Signal(); });
                cnt.Wait();
                foreach (IntegrationRegion subRegion in subRegions) {
                    regionList.AddLast(subRegion);
                }
                */

                foreach (IntegrationRegion subRegion in subRegions) {
                    rule.Evaluate(f, map, subRegion);
                    regionList.AddLast(subRegion);
                }

            }

            throw new NonconvergenceException();
        }
        private static UncertainValue Integrate_Adaptive(MultiFunctor f, CoordinateTransform[] map, IntegrationRegion r, EvaluationSettings settings)
        {
            // Create an evaluation rule
            GenzMalik75Rule rule = new GenzMalik75Rule(r.Dimension);

            // Use it on the whole region and put the answer in a linked list
            rule.Evaluate(f, map, r);
            LinkedList <IntegrationRegion> regionList = new LinkedList <IntegrationRegion>();

            regionList.AddFirst(r);

            // Iterate until convergence
            while (f.EvaluationCount < settings.EvaluationBudget)
            {
                // Add up value and errors in all regions.
                // While we are at it, take note of the region with the largest error.
                double value = 0.0;
                double error = 0.0;
                LinkedListNode <IntegrationRegion> regionNode = regionList.First;
                double maxError = 0.0;
                LinkedListNode <IntegrationRegion> maxErrorNode = null;
                while (regionNode != null)
                {
                    IntegrationRegion region = regionNode.Value;
                    value += region.Value;
                    error += region.Error;
                    //error += MoreMath.Sqr(region.Error);
                    if (region.Error > maxError)
                    {
                        maxError     = region.Error;
                        maxErrorNode = regionNode;
                    }
                    regionNode = regionNode.Next;
                }

                // Check for convergence.
                if ((error <= settings.AbsolutePrecision) || (error <= settings.RelativePrecision * Math.Abs(value)))
                {
                    return(new UncertainValue(value, error));
                }

                // Split the region with the largest error, and evaluate each subregion.
                IntegrationRegion maxErrorRegion = maxErrorNode.Value;
                regionList.Remove(maxErrorNode);
                IList <IntegrationRegion> subRegions = maxErrorRegion.Split(maxErrorRegion.SplitIndex);

                /*
                 * Countdown cnt = new Countdown(2);
                 * ThreadPool.QueueUserWorkItem((object state) => { rule.Evaluate(f, subRegions[0]); cnt.Signal(); });
                 * ThreadPool.QueueUserWorkItem((object state) => { rule.Evaluate(f, subRegions[1]); cnt.Signal(); });
                 * cnt.Wait();
                 * foreach (IntegrationRegion subRegion in subRegions) {
                 *  regionList.AddLast(subRegion);
                 * }
                 */

                foreach (IntegrationRegion subRegion in subRegions)
                {
                    rule.Evaluate(f, map, subRegion);
                    regionList.AddLast(subRegion);
                }
            }

            throw new NonconvergenceException();
        }