/// <summary>
 /// Subtask constructor </summary>
 internal DoubleCumulateTask(DoubleCumulateTask parent, DoubleBinaryOperator function, double[] array, int origin, int fence, int threshold, int lo, int hi) : base(parent)
 {
     this.Function  = function;
     this.Array     = array;
     this.Origin    = origin;
     this.Fence     = fence;
     this.Threshold = threshold;
     this.Lo        = lo;
     this.Hi        = hi;
 }
            /// <summary>
            /// Root task constructor </summary>
            public DoubleCumulateTask(DoubleCumulateTask parent, DoubleBinaryOperator function, double[] array, int lo, int hi) : base(parent)
            {
                this.Function = function;
                this.Array    = array;
                this.Lo       = this.Origin = lo;
                this.Hi       = this.Fence = hi;
                int p;

                this.Threshold = (p = (hi - lo) / (ForkJoinPool.CommonPoolParallelism << 3)) <= MIN_PARTITION ? MIN_PARTITION : p;
            }
            public void Compute()
            {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final java.util.function.DoubleBinaryOperator fn;
                DoubleBinaryOperator fn;

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final double[] a;
                double[] a;
                if ((fn = this.Function) == null || (a = this.Array) == null)
                {
                    throw new NullPointerException();                     // hoist checks
                }
                int th = Threshold, org = Origin, fnc = Fence, l, h;
                DoubleCumulateTask t = this;

                while ((l = t.Lo) >= 0 && (h = t.Hi) <= a.Length)
                {
                    if (h - l > th)
                    {
                        DoubleCumulateTask lt = t.Left, rt = t.Right, f;
                        if (lt == null)                         // first pass
                        {
                            int mid = (int)((uint)(l + h) >> 1);
                            f = rt = t.Right = new DoubleCumulateTask(t, fn, a, org, fnc, th, mid, h);
                            t = lt = t.Left = new DoubleCumulateTask(t, fn, a, org, fnc, th, l, mid);
                        }
                        else                         // possibly refork
                        {
                            double pin = t.@in;
                            lt.@in = pin;
                            f      = t = null;
                            if (rt != null)
                            {
                                double lout = lt.@out;
                                rt.@in = (l == org ? lout : fn.ApplyAsDouble(pin, lout));
                                for (int c;;)
                                {
                                    if (((c = rt.PendingCount) & CUMULATE) != 0)
                                    {
                                        break;
                                    }
                                    if (rt.CompareAndSetPendingCount(c, c | CUMULATE))
                                    {
                                        t = rt;
                                        break;
                                    }
                                }
                            }
                            for (int c;;)
                            {
                                if (((c = lt.PendingCount) & CUMULATE) != 0)
                                {
                                    break;
                                }
                                if (lt.CompareAndSetPendingCount(c, c | CUMULATE))
                                {
                                    if (t != null)
                                    {
                                        f = t;
                                    }
                                    t = lt;
                                    break;
                                }
                            }
                            if (t == null)
                            {
                                break;
                            }
                        }
                        if (f != null)
                        {
                            f.Fork();
                        }
                    }
                    else
                    {
                        int state;                         // Transition to sum, cumulate, or both
                        for (int b;;)
                        {
                            if (((b = t.PendingCount) & FINISHED) != 0)
                            {
                                goto outerBreak;                                 // already done
                            }
                            state = ((b & CUMULATE) != 0? FINISHED : (l > org) ? SUMMED : (SUMMED | FINISHED));
                            if (t.CompareAndSetPendingCount(b, b | state))
                            {
                                break;
                            }
                        }

                        double sum;
                        if (state != SUMMED)
                        {
                            int first;
                            if (l == org)                             // leftmost; no in
                            {
                                sum   = a[org];
                                first = org + 1;
                            }
                            else
                            {
                                sum   = t.@in;
                                first = l;
                            }
                            for (int i = first; i < h; ++i)                             // cumulate
                            {
                                a[i] = sum = fn.ApplyAsDouble(sum, a[i]);
                            }
                        }
                        else if (h < fnc)                         // skip rightmost
                        {
                            sum = a[l];
                            for (int i = l + 1; i < h; ++i)                             // sum only
                            {
                                sum = fn.ApplyAsDouble(sum, a[i]);
                            }
                        }
                        else
                        {
                            sum = t.@in;
                        }
                        t.@out = sum;
                        for (DoubleCumulateTask par;;)                         // propagate
                        {
                            if ((par = (DoubleCumulateTask)t.Completer) == null)
                            {
                                if ((state & FINISHED) != 0)                                 // enable join
                                {
                                    t.QuietlyComplete();
                                }
                                goto outerBreak;
                            }
                            int b = par.PendingCount;
                            if ((b & state & FINISHED) != 0)
                            {
                                t = par;                                 // both done
                            }
                            else if ((b & state & SUMMED) != 0)          // both summed
                            {
                                int nextState;
                                DoubleCumulateTask lt, rt;
                                if ((lt = par.left) != null && (rt = par.right) != null)
                                {
                                    double lout = lt.@out;
                                    par.@out = (rt.Hi == fnc ? lout : fn.ApplyAsDouble(lout, rt.@out));
                                }
                                int refork = (((b & CUMULATE) == 0 && par.lo == org) ? CUMULATE : 0);
                                if ((nextState = b | state | refork) == b || par.compareAndSetPendingCount(b, nextState))
                                {
                                    state = SUMMED;                                     // drop finished
                                    t     = par;
                                    if (refork != 0)
                                    {
                                        par.fork();
                                    }
                                }
                            }
                            else if (par.compareAndSetPendingCount(b, b | state))
                            {
                                goto outerBreak;                                 // sib not ready
                            }
                        }
                    }
                    outerContinue :;
                }
                outerBreak :;
            }